package com.chenfan.mcn.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.chenfan.common.config.Constant;
import com.chenfan.common.exception.BusinessException;
import com.chenfan.common.vo.Response;
import com.chenfan.common.vo.ResponseCode;
import com.chenfan.common.vo.UserVO;
import com.chenfan.mcn.clients.baseinfo.*;
import com.chenfan.mcn.clients.finance.FinanceClient;
import com.chenfan.mcn.clients.privilege.*;
import com.chenfan.mcn.config.UserVoContextHolder;
import com.chenfan.mcn.constant.*;
import com.chenfan.mcn.dao.*;
import com.chenfan.mcn.enums.*;
import com.chenfan.mcn.event.EventPublisher;
import com.chenfan.mcn.event.OperateLogEvent;
import com.chenfan.mcn.exception.McnErrorCode;
import com.chenfan.mcn.exception.RepeatedDataExeception;
import com.chenfan.common.extension.dict.DictStream;
import com.chenfan.common.extension.dict.DictTranslationUtils;
import com.chenfan.mcn.component.CodeGenerateHelper;
import com.chenfan.common.extension.lock.DistributedLockTemplate;
import com.chenfan.mcn.model.*;
import com.chenfan.mcn.model.common.KVPair;
import com.chenfan.mcn.model.dto.*;
import com.chenfan.mcn.model.rpc.ChargeClearCallback;
import com.chenfan.mcn.model.vo.*;
import com.chenfan.mcn.mq.producer.IncomeContractMessageProducer;
import com.chenfan.mcn.service.*;
import com.chenfan.mcn.utils.*;
import com.chenfan.process.vo.ApprovalOperationVO;
import com.chenfan.process.vo.NextNotifyVo;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author tangwei
 * Date:     2021/1/20 10:42
 * Description: 收入合同
 */
@SuppressWarnings({"deprecation", "AlibabaUndefineMagicConstant", "AlibabaRemoveCommentedCode", "AlibabaMethodTooLong"})
@Slf4j
@Service
public class IncomeContractServiceImpl implements IncomeContractService, ApprovalCallbackService {

    @Autowired
    private IncomeContractMapper incomeContractMapper;

    @Autowired
    private ContractExcutionOrderMapper contractExcutionOrderMapper;

    @Autowired
    private DiscountApprovalService discountApprovalService;

    @Autowired
    private BaseInfoClient baseInfoClient;

    @Autowired
    private PrivilegeClient privilegeClient;

    @Autowired
    private YearFrameContractMapper yearFrameContractMapper;

    @Autowired
    private ContractExcutionOrderService contractExcutionOrderService;

    @Autowired
    private IncomeContactAgreementService incomeContactAgreementService;

    @Autowired
    private ApprovalFlowService approvalFlowService;

    @Autowired
    private IncomeContractMessageProducer incomeContractMessageProducer;

    @Autowired
    private MessageInfoService messageInfoService;

    @Autowired
    private FinanceClient financeClient;

    @Autowired
    private ExcuteFeedbackMapper excuteFeedbackMapper;

    @Autowired
    private CalculationDevidedMapper calculationDevidedMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private DocIntentionOrderMapper intentionOrderMapper;

    @Autowired
    private StarPlatformInfoService starPlatformInfoService;

    @Autowired
    private LiveContractCommodityMapper liveContractCommodityMapper;

    @Autowired
    private LiveContactOfflineCommissionService liveContactOfflineCommissionService;

    @Autowired
    private StarBasicDataMapper starBasicDataMapper;

    @Autowired
    private BrandInfoService brandInfoService;

    private static final String APPROVAL_KEY = "approval::contract::";

    @Value("${zxd_payback_effectiveTime:2023-08-30 22:30:00}")
    private String zxdPaybackEffectiveTimeStr;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long addIncomeContract(IncomeContractAddDTO incomeContractAddDTO) {
        if(CollectionUtils.isNotEmpty(incomeContractAddDTO.getExcutionOrders())) {
            incomeContractAddDTO.getExcutionOrders().forEach(e -> {
                //关联字段忽略
                e.setContractAgreementId(null);
                e.setStarRebateId(null);
                e.setStarRebateCode(null);
                e.setPurchaseCode(null);
                e.setAccountId(null);
                e.setAccountType(null);
                e.setHandlingFeeRate(null);
                e.setPaidWay(null);
                e.setPaidRemark(null);
                e.setPaidStarDate(null);
                e.setYearCode(null);
                e.setDepartmentHeaderId(null);
                e.setDepartmentHeaderName(null);
                e.setStartExecutionDate(null);
                e.setInSystemAdmin(null);
                e.setCustomerInvoiceWay(null);
                e.setTransitDate(null);
                e.setApprovalBy(null);
                e.setApprovalName(null);
                e.setApprovalDate(null);
                e.setInvoiceForm(null);
                e.setInvoiceTitle(null);
                e.setInvoiceContent(null);
                e.setInvoiceType(null);
                e.setStarBillingHeaderId(null);
                e.setCommissionSettleStatus(null);
                e.setBusinessCommissionSettleStatus(null);
                //公共字段忽略
                e.ignore();
            });
        }
        incomeContractAddDTO.setTotalAmount(ObjectUtils.defaultIfNull(incomeContractAddDTO.getTotalAmount(), BigDecimal.ZERO));
        initOfflineCommissionInfo(incomeContractAddDTO);
        if (IncomeContractTypeEnum.isFormalContract(incomeContractAddDTO.getContractType())) {
            incomeContractAddDTO.setContractTag(null);
            incomeContractAddDTO.setInSystemAdmin(null);
        }
        Long id = this.saveIncomeContract(incomeContractAddDTO);
        this.startProcess(incomeContractAddDTO);
        //操作日志
        EventPublisher.post(OperateLogEvent.builder().businessId(id).businessType(LogBusinessTypeEnum.INCOME_CONTRACT)
                .insert(ApprovalStatusEnum.isApproval(incomeContractAddDTO.getApprovalStatus()) ? LogTemplateCst.ADD_APPROVAL : LogTemplateCst.ADD,
                        LogBusinessTypeEnum.INCOME_CONTRACT.getDesc(), incomeContractAddDTO.getContractCode()).build());
        return id;
    }

    private void initOfflineCommissionInfo(IncomeContractAddDTO incomeContractAddDTO) {
        if (IncomeContractTypeEnum.isLiveContract(incomeContractAddDTO.getContractType())) {
            //如果用户填写了【线下佣金应收金额】之后，更新此字段的值，收入总金额=保ROI广告收入+不保ROI广告收入+保ROI直播收入+不保ROI直播收入+保ROI其他收入+不保ROI其他收入+线下佣金应收金额
            incomeContractAddDTO.setBusinessAmount(ObjectUtils.defaultIfNull(incomeContractAddDTO.getRoiAdvAmt(), BigDecimal.ZERO)
                    .add(ObjectUtils.defaultIfNull(incomeContractAddDTO.getRoiLiveAmt(), BigDecimal.ZERO))
                    .add(ObjectUtils.defaultIfNull(incomeContractAddDTO.getRoiOhterAmt(), BigDecimal.ZERO))
                    .add(ObjectUtils.defaultIfNull(incomeContractAddDTO.getNoroiAdvAmt(), BigDecimal.ZERO))
                    .add(ObjectUtils.defaultIfNull(incomeContractAddDTO.getNoroiLiveAmt(), BigDecimal.ZERO))
                    .add(ObjectUtils.defaultIfNull(incomeContractAddDTO.getNoroiOhterAmt(), BigDecimal.ZERO))
                    .add(ObjectUtils.defaultIfNull(incomeContractAddDTO.getOfflineCommissionAmount(), BigDecimal.ZERO)));
//            incomeContractAddDTO.setBusinessAmount(ObjectUtils.defaultIfNull(incomeContractAddDTO.getPitFeeAmount(), BigDecimal.ZERO)
//                    .add(ObjectUtils.defaultIfNull(incomeContractAddDTO.getRoiServiceFee(), BigDecimal.ZERO))
//                    .add(ObjectUtils.defaultIfNull(incomeContractAddDTO.getAdAmount(), BigDecimal.ZERO)));
            incomeContractAddDTO.setOfflineCommissionAmount(null);
            incomeContractAddDTO.setAdAmount(null);
            incomeContractAddDTO.setLiveAmount(null);
            incomeContractAddDTO.setOfflineCommissionSettleStatus(NumberCst.ZERO);
            incomeContractAddDTO.setOfflineCommissionPaybackAmount(BigDecimal.ZERO);
            if ("0".equals(incomeContractAddDTO.getOfflineCommissionRate())) {
                incomeContractAddDTO.setOfflineCommissionSettleStatus(NumberCst.FOUR);
            } else {
                incomeContractAddDTO.setOfflineCommissionSettleStatus(NumberCst.ZERO);
            }
//            if (!CooperationTypeEnum.contains(incomeContractAddDTO.getCooperationType(), CooperationTypeEnum.OFFLINE_STRAIGHT_COMMISSION)) {
//                incomeContractAddDTO.setOfflineCommissionSettleStatus(NumberCst.FOUR);
//            }
        } else {
            incomeContractAddDTO.setOfflineCommissionSettleStatus(NumberCst.FOUR);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long updateIncomeContract(IncomeContractAddDTO incomeContractAddDTO) {
        initOfflineCommissionInfo(incomeContractAddDTO);
        Long id = this.saveIncomeContract(incomeContractAddDTO);
        this.startProcess(incomeContractAddDTO);
        return id;
    }

    /**
     * 启动流程审批
     *
     * @param dto
     */
    public void startProcess(IncomeContractAddDTO dto) {
        if (ApprovalStatusEnum.isApproval(dto.getApprovalStatus())) {
            this.verifyParams(dto, incomeContractMapper.getPlatformOrderNumber(), dto.getExcutionOrders());
            IncomeContract incomeContract = incomeContractMapper.selectById(dto.getId());
            if (this.verifyExcutionAmountIfNecessary(incomeContract.getContractType(), dto.getExcutionOrders(), incomeContract.getBusinessAmount())) {
                updateExpectedAmount(incomeContract.getId());
            }
            approvalFlowService.startProcess(incomeContract.getId(), incomeContract.getContractCode(), ApprovalEnum.getEnumByContractType(incomeContract.getContractType()), JSON.toJSONString(dto));
            if (InvoiceFormEnum.needAutoInvoice(dto.getInvoiceForm())) {
                stringRedisTemplate.opsForValue().set(Constant.AUTHORIZATION + ":" + APPROVAL_KEY + dto.getContractCode(), JSONObject.toJSONString(UserVoContextHolder.getUserVo()), 100, TimeUnit.DAYS);
            }
        }
    }

    @Override
    public boolean updateExpectedAmount(Long incomeContractId) {
        return DistributedLockTemplate.execute(OperateLockEnum.INCOME_CONTRACT.generateKey(incomeContractId), () -> {
                    BigDecimal expectedAmount = this.getExpectedAmount(incomeContractId);
                    IncomeContract updateIncomeContract = new IncomeContract();
                    updateIncomeContract.setId(incomeContractId);
                    updateIncomeContract.setExpectedAmount(expectedAmount);
                    return incomeContractMapper.updateById(updateIncomeContract) > 0;
                }
        );
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void setExpectedAmount() {
        List<IncomeContract> incomeContractList = incomeContractMapper.selectList(Wrappers.lambdaQuery(IncomeContract.class)
                .eq(IncomeContract::getIsDelete, Boolean.FALSE)
                .and(wrapper -> wrapper.eq(IncomeContract::getApprovalStatus, ApprovalStatusEnum.APPROVAL.getCode())
                        .or().eq(IncomeContract::getApprovalStatus, ApprovalStatusEnum.PASSED.getCode())));
        if (CollectionUtils.isNotEmpty(incomeContractList)) {
            incomeContractList.forEach(x -> updateExpectedAmount(x.getId()));
        }
    }

    @Override
    public void setSingleExpectedAmount(Long incomeContractId) {
        IncomeContract incomeContract = incomeContractMapper.selectById(incomeContractId);
        BusinessAssert.notNull(incomeContract, McnErrorCode.INCOME_NOT_EXISTS);
        updateExpectedAmount(incomeContract.getId());
    }

    @Override
    public List<ContractExcutionOrder> confirmedAmount(Long id) {
        return incomeContractMapper.confirmedAmount(id);
    }

    @Override
    public BigDecimal getAmountOfMoney(List<String> incomeCodes) {
        return incomeContractMapper.getAmountOfMoney(incomeCodes);
    }

    @Override
    public boolean legalApproval(IncomeContractLegalApprovalDTO dto) {
        IncomeContract incomeContract = incomeContractMapper.selectOne(Wrappers.lambdaQuery(IncomeContract.class)
                .eq(IncomeContract::getId, dto.getId()).eq(IncomeContract::getIsDelete, NumberCst.ZERO));
        BusinessAssert.notNull(incomeContract, McnErrorCode.INCOME_NOT_EXISTS);
        BusinessAssert.isTrue(ApprovalStatusEnum.isApproval(incomeContract.getApprovalStatus()), McnErrorCode.BUSINESS_ERROR, "非法操作！收入合同非审批中");
        return incomeContractMapper.updateByNoStrategy(Wrappers.lambdaUpdate(IncomeContract.class)
                .set(IncomeContract::getContractTag, dto.getContractTag())
                .set(IncomeContract::getUpdateBy, UserVoContextHolder.getUserId())
                .set(IncomeContract::getUpdateName, UserVoContextHolder.getUserName())
                .set(IncomeContract::getUpdateDate, new Date())
                .eq(IncomeContract::getId, dto.getId()) );
    }

    @Override
    public Page<AnnualRebateIncomeContractListVO> queryIncomeContractByPage(AnnualRebateQueryContractDTO queryContractDTO) {
        Page<AnnualRebateIncomeContractListVO> page = new Page<>(queryContractDTO.getPageNum(), queryContractDTO.getPageSize());
        return incomeContractMapper.queryIncomeContractByPage(page, queryContractDTO);
    }

    @Override
    public Page<LiveContractSelectVO> queryUnClaimLiveContract(LiveContractQueryDto dto) {
        Page<LiveContractSelectVO> page = incomeContractMapper.queryUnClaimLiveContract(new Page<>(dto.getPageNum(), dto.getPageSize()), dto);
        if(CollectionUtils.isNotEmpty(page.getRecords())) {
            DictTranslationUtils.translation(() -> DictStream.of(
                    DictStream.map(DictTypeCst.ACTIVE_PLATFORMS, LiveContractSelectVO::getLivePlatform, LiveContractSelectVO::setLivePlatformName)
                    ),
                    (dictProfileList, dictList) -> Objects.requireNonNull(baseInfoClient.getDescByCode(new DescByCodeDTO()
                            .setDictsCodes(dictList.stream().distinct().collect(Collectors.toList())).setProfileCodes(dictProfileList))).getObj(),
                    page.getRecords()
            );
            List<String> brandCodes = page.getRecords().stream().map(LiveContractSelectVO::getCooperateBrand).filter(Objects::nonNull).distinct().collect(Collectors.toList());
            Map<String,String> brandMap = brandInfoService.getBrandMapByCodes(brandCodes);
            List<Long> customerIds = page.getRecords().stream().map(LiveContractSelectVO::getCustomerId).distinct().collect(Collectors.toList());
            Map<Long, BaseCustomer> customerMap = baseInfoClient.getMcnCustomerByIds(customerIds).getObj();
            page.getRecords().forEach(data -> {
                if(brandMap.containsKey(data.getCooperateBrand())) {
                    data.setCooperateBrandName(brandMap.get(data.getCooperateBrand()));
                }
                if(CommonUtil.containsKey(customerMap, data.getCustomerId())) {
                    data.setCustomerName(customerMap.get(data.getCustomerId()).getCustomerNameC());
                }
            });
        }
        return page;
    }

    @Override
    public Long updatePerformanceSharer(PerformanceSharerUpdateDTO dto) {
        IncomeContract incomeContract = incomeContractMapper.selectOne(Wrappers.lambdaQuery(IncomeContract.class)
                .eq(IncomeContract::getId, dto.getIncomeContractId()).eq(IncomeContract::getIsDelete, NumberCst.ZERO));
        BusinessAssert.notNull(incomeContract, McnErrorCode.INCOME_NOT_EXISTS);
        BusinessAssert.isTrue(ApprovalStatusEnum.isPassed(incomeContract.getApprovalStatus()), McnErrorCode.BUSINESS_ERROR, "非审批通过，不允许更换业绩共享人");
        SUser sUser = privilegeClient.getUserById(dto.getPerformanceSharerId()).getObj();
        BusinessAssert.isTrue(Objects.nonNull(sUser) && NumberCst.ZERO.equals(sUser.getStatus()), McnErrorCode.BUSINESS_ERROR, "该业绩共享人非在职");
        IncomeContract updateIncomeContract = new IncomeContract();
        updateIncomeContract.setId(incomeContract.getId());
        updateIncomeContract.setPerformanceShare(NumberCst.ONE);
        updateIncomeContract.setPerformanceSharerId(sUser.getUserId());
        updateIncomeContract.setPerformanceSharerName(sUser.getUsername());
        this.performanceSharerDepartmentId(updateIncomeContract);
        incomeContractMapper.updateById(updateIncomeContract);
        //操作日志
        EventPublisher.post(OperateLogEvent.builder().businessId(incomeContract.getId())
                .businessType(LogBusinessTypeEnum.INCOME_CONTRACT)
                .compare(incomeContract, incomeContractMapper.selectById(incomeContract.getId()))
                .build());
        return incomeContract.getId();
    }

    @Override
    public Long regenerateIncomeFee(Long incomeContractId) {
        if (!stringRedisTemplate.opsForValue().setIfAbsent(OperateLockEnum.INCOME_CONTRACT_REPUSH.generateKey(incomeContractId), "repushMq", NumberCst.FIVE, TimeUnit.SECONDS).booleanValue()) {
            throw new BusinessException(McnErrorCode.BUSINESS_ERROR.code(), "请勿频繁操作，5秒后再试！");
        }
        IncomeContract incomeContract = incomeContractMapper.selectOne(Wrappers.lambdaQuery(IncomeContract.class)
                .eq(IncomeContract::getId, incomeContractId).eq(IncomeContract::getIsDelete, NumberCst.ZERO));
        BusinessAssert.notNull(incomeContract, McnErrorCode.INCOME_NOT_EXISTS);
        BusinessAssert.isTrue(ApprovalStatusEnum.isPassed(incomeContract.getApprovalStatus()), McnErrorCode.BUSINESS_ERROR, "非审批通过，不允许重新生成费用");
        //如果非框架合同且合同金额等于0 则不产生费用
        if(IncomeContractTypeEnum.isLiveContract(incomeContract.getContractType()) ||
                ObjectUtils.defaultIfNull(incomeContract.getBusinessAmount(), BigDecimal.ZERO).compareTo(BigDecimal.ZERO) != 0) {
            incomeContractMessageProducer.sendRecordToMq(new ImmutablePair<>(incomeContract.getId(), Boolean.TRUE));
        }
        return incomeContract.getId();
    }

    @SuppressWarnings("AlibabaMethodTooLong")
    @Override
    public IncomeContractDetailVO incomeContractDetail(Long id) {
        IncomeContractDetailVO incomeContractDetailVO = new IncomeContractDetailVO();
        IncomeContractVO incomeContract = incomeContractMapper.infoData(id, ApprovalEnum.getContractProcessIds(), ApprovalEnum.INCOME_LIVE_CONTRACT_OFFLINE_COMMISSION.getProcessId());
        BusinessAssert.notNull(incomeContract, McnErrorCode.INCOME_NOT_EXISTS);
        //合同基础信息
        BeanUtils.copyProperties(incomeContract, incomeContractDetailVO);
        if (IncomeContractTypeEnum.isLiveContract(incomeContract.getContractType())) {
            //参与保比收入总计
            incomeContractDetailVO.setIncomeTotal(ObjectUtils.defaultIfNull(incomeContract.getRoiAdvAmt(), BigDecimal.ZERO)
                    .add(ObjectUtils.defaultIfNull(incomeContract.getRoiLiveAmt(), BigDecimal.ZERO))
                    .add(ObjectUtils.defaultIfNull(incomeContract.getRoiOhterAmt(), BigDecimal.ZERO)));
            //不参与保比收入总计
            incomeContractDetailVO.setNoIncomeTotal(ObjectUtils.defaultIfNull(incomeContract.getNoroiAdvAmt(), BigDecimal.ZERO)
                    .add(ObjectUtils.defaultIfNull(incomeContract.getNoroiLiveAmt(), BigDecimal.ZERO))
                    .add(ObjectUtils.defaultIfNull(incomeContract.getNoroiOhterAmt(), BigDecimal.ZERO)));
        }
        log.info("应收总金额:{}",incomeContract.getBusinessAmount());

        //查询收入合同品牌
        incomeContractDetailVO.setCooperateBrandName(brandInfoService.getBrandNameByCode(incomeContract.getCooperateBrand()));

        //直播合同商品信息
        if (IncomeContractTypeEnum.isLiveContract(incomeContract.getContractType())) {
            List<LiveContractCommodityDetailVO> liveContractCommodities = CommonUtil.defaultList(
                    liveContractCommodityMapper.getLiveCommodityDetailsByContractId(incomeContract.getId())
            ).stream().map(e -> {
                LiveContractCommodityDetailVO detailVO = new LiveContractCommodityDetailVO();
                BeanUtils.copyProperties(e, detailVO);
                return detailVO;
            }).collect(Collectors.toList());
            if(CollectionUtils.isNotEmpty(liveContractCommodities)) {
                List<String> brandCodes = liveContractCommodities.stream().map(LiveContractCommodityDetailVO::getCooperateBrand).filter(Objects::nonNull).distinct().collect(Collectors.toList());
                Map<String,String> brandMap = brandInfoService.getBrandMapByCodes(brandCodes);
                liveContractCommodities.forEach(e -> {
                    if(brandMap.containsKey(e.getCooperateBrand())) {
                        e.setCooperateBrandName(brandMap.get(e.getCooperateBrand()));
                    }
                });
                DictTranslationUtils.translation(() -> DictStream.of(
                        DictStream.map(DictTypeCst.ACTIVE_PLATFORMS, LiveContractCommodityDetailVO::getLivePlatform, LiveContractCommodityDetailVO::setLivePlatformName),
                        DictStream.map(DictTypeCst.LIVE_CONTRACT_CATEGORY, LiveContractCommodityDetailVO::getLiveContractCategory, LiveContractCommodityDetailVO::setLiveContractCategoryName)
                        ),(dictProfileList, dictList) -> baseInfoClient.getDescByCode(new DescByCodeDTO().setDictsCodes(dictList).setProfileCodes(dictProfileList)).getObj(),
                        liveContractCommodities
                );
            }
            incomeContractDetailVO.setLiveContractCommodityList(liveContractCommodities);
        }

        //查审批流
        JSONObject flowMapping = approvalFlowService.getFlowStatus(Lists.newArrayList(incomeContractDetailVO.getFlowId()));
        incomeContractDetailVO.setFlowStatusName(CommonUtil.defaultString(flowMapping, incomeContractDetailVO.getFlowId()));

        //主播名称
        if(Objects.nonNull(incomeContractDetailVO.getStarPlatformInfoId())) {
            StarPlatformInfo starPlatformInfo = starPlatformInfoService.selectById(incomeContractDetailVO.getStarPlatformInfoId());
            BusinessAssert.notNull(starPlatformInfo, McnErrorCode.DATA_NOT_FOUND, "红人平台信息不存在");
            incomeContractDetailVO.setAnchorName(StringUtils.joinWith(SeparatorCst.MINUS, starPlatformInfo.getPlatNickName(), starPlatformInfo.getPlatformName()));
        }
        //开票信息
        if (Objects.nonNull(incomeContractDetailVO.getCustomerBillingId())) {
            BaseCustomerBillingVO baseCustomerBillingVO = baseInfoClient.getBillingsInfoById(incomeContractDetailVO.getCustomerBillingId()).getObj();
            if (Objects.isNull(baseCustomerBillingVO)) {
                baseCustomerBillingVO = new BaseCustomerBillingVO();
            }
            incomeContractDetailVO.setBillingDetails(baseCustomerBillingVO);
        }
        if (Objects.isNull(incomeContractDetailVO.getBillingDetails())) {
            incomeContractDetailVO.setBillingDetails(new BaseCustomerBillingVO());
        }

        //折扣审批单
        DiscountInfoVO discountInfoVO = new DiscountInfoVO();
        if (Objects.nonNull(incomeContractDetailVO.getDiscountId())) {
            discountInfoVO = discountApprovalService.getDiscountApprovalInfo(incomeContractDetailVO.getDiscountId());
            incomeContractDetailVO.setDiscountInfoVO(discountInfoVO);
        }
        //年框合同
        yearFrameContractVoInfo(incomeContractDetailVO);
        if (incomeContractDetailVO.getYearContractId() != null) {
            YearFrameContract yearFrameContract = yearFrameContractMapper.geteffectiveContract(incomeContractDetailVO.getYearContractId());
            if (yearFrameContract != null) {
                discountInfoVO.setYearContractId(yearFrameContract.getId());
                discountInfoVO.setYearContractCode(yearFrameContract.getYearFrameCode());
            }
        }
        //补充协议
        List<ContractAgreementVO> agreementList = incomeContactAgreementService.agreementList(id, incomeContract.getContractType());
        incomeContractDetailVO.setAgreementList(agreementList);

        //执行单
        List<ContractExcutionOrder> executionOrders = contractExcutionOrderService.getByContractId(id);

        //查询意向单
        List<Long> excuteOrderIds = executionOrders.stream().map(x -> x.getId()).collect(Collectors.toList());
        Map<Long, DocIntentionOrder> intentionOrderMap = CommonUtil.getIfNecessary(CollectionUtils.isNotEmpty(excuteOrderIds), () ->
                        CommonUtil.defaultList(intentionOrderMapper.selectList(Wrappers.lambdaQuery(DocIntentionOrder.class).in(DocIntentionOrder::getExcutionOrderId, excuteOrderIds)))
                                .stream().collect(Collectors.toMap(DocIntentionOrder::getExcutionOrderId, x -> x, (x, y) -> x))
                , Collections.EMPTY_MAP);

        //查询客户资料
        List<Long> customerIdList = CommonUtil.defaultList(executionOrders).stream().map(x -> x.getCustomerId()).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        customerIdList.add(incomeContract.getCustomerId());
        Map<Long, BaseCustomer> baseCustomerMap = CommonUtil.getIfNecessary(CollectionUtils.isNotEmpty(customerIdList), () ->
                baseInfoClient.getMcnCustomerByIds(customerIdList).getObj(), Collections.EMPTY_MAP);
        CustomerVO customerVO = new CustomerVO();
        BaseCustomer baseCustomer = baseCustomerMap.get(incomeContract.getCustomerId());
        BusinessAssert.notNull(baseCustomer, McnErrorCode.DATA_NOT_FOUND);
        BeanUtils.copyProperties(baseCustomer, customerVO);
        customerVO.setCustomerState(baseCustomer.getCustomerState());
        incomeContractDetailVO.setCustomerName(baseCustomerMap.get(incomeContract.getCustomerId()).getCustomerNameC());

        //设置客户档案&收入合同-创建人所属部门
        List<SUserVo> userList = privilegeClient.getDepartmentByUserIds(Lists.newArrayList(baseCustomer.getCreateBy())).getObj();
        if (CollectionUtils.isNotEmpty(userList)) {
            Map<Long, SUserVo> sUserVoMap = userList.stream().collect(Collectors.toMap(SUserVo::getUserId, sUserVo -> sUserVo));
            if (CommonUtil.containsKey(sUserVoMap, customerVO.getCreateBy())) {
                customerVO.setDepartmentName(sUserVoMap.get(customerVO.getCreateBy()).getDepartmentName());
            }
        }
        Map<Long, SDepartment> userMap = privilegeClient.getDepartmentByIds(Arrays.asList(incomeContract.getDepartmentId())).getObj();
        if (CommonUtil.containsKey(userMap, incomeContract.getDepartmentId())) {
            incomeContractDetailVO.setDepartmentName(userMap.get(incomeContract.getDepartmentId()).getDepartmentName());
        }

        //获取Publishing_platform数据字典
        if (CollectionUtil.isNotEmpty(executionOrders)) {
            //查询红人信息*客户信息
            List<BasicExcutionOrderVO> excutionOrdersVO = contractExcutionOrderService.basicExcutionOrderList(executionOrders);
            excutionOrdersVO.forEach(e -> {
                BaseCustomer customer = baseCustomerMap.get(e.getCustomerId());
                if (Objects.nonNull(customer)) {
                    e.setCustomerId(customer.getCustomerId());
                    e.setCustomerName(customer.getCustomerNameC());
                    e.setCustomerCode(customer.getCustomerCode());
                }
                e.setPlatformOrderNumber(e.getPlatformOrderCode());
                //如果字段无用，
                e.setBrandNameN(e.getBrandNameN());
                DocIntentionOrder intentionOrder = intentionOrderMap.get(e.getId());
                if(Objects.nonNull(intentionOrder)) {
                    e.setIntentionOrderId(intentionOrder.getId());
                    e.setIntentionCode(intentionOrder.getIntentionCode());
                    e.setIsLiveAd(intentionOrder.getIsLiveAd());
                    e.setHaveDiscountApproval(intentionOrder.getHaveDiscountApproval());
                    e.setDiscountScreenshot(intentionOrder.getDiscountScreenshot());
                }
            });
            incomeContractDetailVO.setExcutionOrders(excutionOrdersVO);
        }

        //合同基础信息数据字典
        List<String> profileCodes = Arrays.asList("formal_contract", "SubjectOfContract", "Source_of_contract", "Release_type", "liveContractCategory",
                "Customer_classification", "Customer_source", "Brand_sales_channel", "Customer_status", "Customer_rating", "cooperationType", "incomeContractTag");
        List<String> classifications = Arrays.asList(customerVO.getCustomerClassification().split(","));
        List<String> dict = new ArrayList<>(classifications);
        dict.add(incomeContract.getFormalContractType());
        dict.add(incomeContract.getCompanyContractSubject());
        dict.add(incomeContract.getCooperateSource());
        if(StringUtils.isNotBlank(incomeContract.getCooperationType())) {
            dict.addAll(Arrays.asList(incomeContract.getCooperationType().split(SeparatorCst.COMMA)));
        }
        dict.add(incomeContract.getLiveContractCategory());
        dict.add(customerVO.getBrandCategory());
        dict.add(customerVO.getCustomerSource());
        if(StringUtils.isNotBlank(customerVO.getBrandDistributionChannel())) {
            dict.addAll(Arrays.asList(customerVO.getBrandDistributionChannel().split(SeparatorCst.COMMA)));
        }
        dict.add(customerVO.getCustomerState());
        dict.add(customerVO.getCustomerScore());
        if (CollectionUtil.isNotEmpty(executionOrders)) {
            executionOrders.forEach(e -> {
                dict.add(e.getCategory());
                dict.add(e.getPublishType());
                if (StringUtils.isNotBlank(e.getOrderPlatform())) {
                    dict.add(e.getOrderPlatform());
                }
                dict.add(e.getBrandName());
            });
        }
        if (StringUtils.isNotBlank(incomeContract.getContractTag())) {
            dict.add(incomeContract.getContractTag());
        }
        refactor(incomeContractDetailVO, incomeContract, customerVO, baseCustomer, profileCodes, classifications, dict);
        return incomeContractDetailVO;
    }

    private void yearFrameContractVoInfo(IncomeContractDetailVO incomeContractDetailVO) {
        if (Objects.nonNull(incomeContractDetailVO.getYearContractId())) {
            YearFrameContract yearFrameContract = yearFrameContractMapper.selectById(incomeContractDetailVO.getYearContractId());
            YearFrameContractVO yearFrameContractVO = new YearFrameContractVO();
            BeanUtils.copyProperties(yearFrameContract, yearFrameContractVO);
            List<String> dictProfileList = new ArrayList<>(Collections.singletonList("yearFrameContract"));
            List<String> dictList = Collections.singletonList(yearFrameContractVO.getContractType());
            Map<String, String> dictMapping = Objects.requireNonNull(baseInfoClient.getDescByCode(new DescByCodeDTO()
                    .setDictsCodes(dictList).setProfileCodes(dictProfileList))).getObj();
            if (Objects.nonNull(dictMapping)) {
                yearFrameContractVO.setContractTypeName(dictMapping.get(dictProfileList.get(0) + ";" + yearFrameContractVO.getContractType()));
            }
            incomeContractDetailVO.setYearFrameContractVO(yearFrameContractVO);
        } else {
            incomeContractDetailVO.setYearFrameContractVO(new YearFrameContractVO());
        }
    }

    private Map<String, String> refactor(IncomeContractDetailVO incomeContractDetailVO, IncomeContractVO incomeContract, CustomerVO customerVO, BaseCustomer baseCustomer, List<String> profileCodes, List<String> splitclassifications, List<String> dict) {
        //查询并设置数据字典中文名称
        DescByCodeDTO descByCodeDTO = new DescByCodeDTO();
        descByCodeDTO.setProfileCodes(profileCodes);
        descByCodeDTO.setDictsCodes(dict);
        Map<String, String> dictsNameMap = baseInfoClient.getDescByCode(descByCodeDTO).getObj();
        incomeContractDetailVO.setFormalContractTypeName(dictsNameMap.get("formal_contract" + ";" + incomeContract.getFormalContractType()));
        incomeContractDetailVO.setCompanyContractSubjectName(dictsNameMap.get("SubjectOfContract" + ";" + incomeContract.getCompanyContractSubject()));
        incomeContractDetailVO.setCooperateSourceName(dictsNameMap.get("Source_of_contract" + ";" + incomeContract.getCooperateSource()));
//        if (StringUtils.isNotBlank(incomeContract.getCooperationType())) {
//            List<String> cooperationTypeNameList = Stream.of(incomeContract.getCooperationType().split(SeparatorCst.COMMA))
//                    .map(e -> dictsNameMap.get("cooperationType" + ";" + e)).collect(Collectors.toList());
//            incomeContractDetailVO.setCooperationTypeName(String.join(SeparatorCst.COMMA, cooperationTypeNameList));
//        }
        incomeContractDetailVO.setLiveContractCategoryName(dictsNameMap.get("liveContractCategory" + ";" + incomeContract.getLiveContractCategory()));
        if(StringUtils.isNotBlank(incomeContract.getContractTag())) {
            incomeContractDetailVO.setContractTagName(dictsNameMap.get("incomeContractTag" + ";" + incomeContract.getContractTag()));
        }
        customerVO.setCustomerSource(dictsNameMap.get("Customer_source" + ";" + baseCustomer.getCustomerSource()));
        customerVO.setBrandCategory(dictsNameMap.get("BrandCategory" + ";" + baseCustomer.getBrandCategory()));
        if(StringUtils.isNotBlank(customerVO.getBrandDistributionChannel())) {
            List<String> brandDistributionChannelNameList = Stream.of(customerVO.getBrandDistributionChannel().split(SeparatorCst.COMMA))
                    .map(e -> dictsNameMap.get("Brand_sales_channel" + ";" + e)).collect(Collectors.toList());
            customerVO.setBrandDistributionChannel(String.join(SeparatorCst.COMMA, brandDistributionChannelNameList));
        }
        customerVO.setCustomerState(dictsNameMap.get("Customer_status" + ";" + baseCustomer.getCustomerState()));
        customerVO.setCustomerScore(dictsNameMap.get("Customer_rating" + ";" + baseCustomer.getCustomerScore()));
        StringBuffer sb = new StringBuffer();
        String comma = ",";
        for (String splitclassification : splitclassifications) {
            sb.append(dictsNameMap.get("Customer_classification" + ";" + splitclassification)).append(comma);
        }
        customerVO.setCustomerClassificationName(sb.substring(0, sb.length() - 1));
        incomeContractDetailVO.setCustomerVO(customerVO);
        return dictsNameMap;
    }

    @Override
    public Page<IncomeContractListVO> getContractPage(McnPage<IncomeContractListVO> mcnPage, IncomeContractSearchDTO incomeContractSearchDTO) {
        mcnPage.setPageNum(incomeContractSearchDTO.getPageNum());
        mcnPage.setPageSize(incomeContractSearchDTO.getPageSize());
        incomeContractSearchDTO.setAlias("ic.");
        incomeContractSearchDTO.setProcessIds(ApprovalEnum.getContractProcessIdsWithOfflineCommission());
        if (CollectionUtils.isNotEmpty(incomeContractSearchDTO.getFlowStatus())) {
            List<Long> allList = approvalFlowService.getSrcList(incomeContractSearchDTO.getFlowStatus(), incomeContractSearchDTO.getProcessIds());
            if (CollectionUtil.isEmpty(allList)) {
                return new Page<>();
            }
            incomeContractSearchDTO.setSrcIds(allList);
        }
        Page<IncomeContractListVO> contractPage = incomeContractMapper.getContractPage(mcnPage, incomeContractSearchDTO);
        List<IncomeContractListVO> contractList = contractPage.getRecords();
        if (CollectionUtil.isNotEmpty(contractList)) {
            //查询FlowId
            List<Long> idList = contractList.stream().map(IncomeContractListVO::getId).collect(Collectors.toList());
            Map<Long, Long> flowMap = approvalFlowService.getNewestFlowIds(idList, ApprovalEnum.getContractProcessIds());
            if (CollectionUtils.isNotEmpty(flowMap)) {
                contractList.forEach(contract -> {
                    contract.setFlowId(flowMap.get(contract.getId()));
                });
            }
            //查询客户名称
            List<Long> customerIdList = contractList.stream().map(IncomeContractListVO::getCustomerId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
            Map<Long, BaseCustomer> customerMap = baseInfoClient.getMcnCustomerByIds(customerIdList).getObj();
            //审批名称
            List<Long> flowIdList = contractList.stream().map(IncomeContractListVO::getFlowId).filter(Objects::nonNull).collect(Collectors.toList());
            JSONObject flowMapping = approvalFlowService.getFlowStatus(flowIdList);
            contractList.forEach(contract -> {
                if (Objects.nonNull(contract.getCustomerId()) && CommonUtil.containsKey(customerMap, contract.getCustomerId())) {
                    contract.setCustomerName(customerMap.get(contract.getCustomerId()).getCustomerNameC());
                }
                if(MapUtils.isNotEmpty(flowMapping)) {
                    contract.setFlowStatusName(CommonUtil.defaultString(flowMapping, contract.getFlowId()));
                }
            });
        }
        return contractPage;
    }

    @Override
    public List<BasicContractVO> getContractList(IncomeContractSearchDTO incomeContractSearchDTO) {
        incomeContractSearchDTO.setAlias("ic.");
        incomeContractSearchDTO.setApprovalStatus(Collections.singletonList(ApprovalStatusEnum.PASSED.code()));
        List<BasicContractVO> dataList = incomeContractMapper.getContractList(incomeContractSearchDTO);
        /*if (CollectionUtils.isNotEmpty(dataList)) {
            List<Long> excuteOrderIds = dataList.stream().filter(e -> Objects.nonNull(e.getExcuteOrderId())).map(BasicContractVO::getExcuteOrderId).distinct().collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(excuteOrderIds)) {
                List<BasicExcutionOrderVO> excutionOrderList = contractExcutionOrderMapper.selectList(Wrappers.lambdaQuery(ContractExcutionOrder.class)
                        .select(ContractExcutionOrder::getId, ContractExcutionOrder::getBrandName, ContractExcutionOrder::getProductName, ContractExcutionOrder::getCategory,
                                ContractExcutionOrder::getExcutorId, ContractExcutionOrder::getExcutorName)
                        .in(ContractExcutionOrder::getId, excuteOrderIds))
                        .stream().map(excutionOrder -> {
                            BasicExcutionOrderVO basicExcutionOrderVO = new BasicExcutionOrderVO();
                            BeanUtils.copyProperties(excutionOrder, basicExcutionOrderVO);
                            return basicExcutionOrderVO;
                        }).collect(Collectors.toList());
                if(CollectionUtils.isNotEmpty(excutionOrderList)) {
                    List<String> brandCodes = excutionOrderList.stream().map(BasicExcutionOrderVO::getBrandName).filter(Objects::nonNull).distinct().collect(Collectors.toList());
                    Map<String,String> brandMap = brandInfoService.getBrandMapByCodes(brandCodes);
                    excutionOrderList.forEach(e -> {
                        if(brandMap.containsKey(e.getBrandName())) {
                            e.setBrandNameN(brandMap.get(e.getBrandName()));
                        }
                    });
                    //字典翻译
                    DictTranslationUtils.translation(() -> DictStream.of(
                            DictStream.map("BrandCategory", BasicExcutionOrderVO::getCategory, BasicExcutionOrderVO::setCategoryName)
                            ),(dictProfileList, dictList)
                                    -> baseInfoClient.getDescByCode(new DescByCodeDTO().setDictsCodes(dictList).setProfileCodes(dictProfileList)).getObj(),
                            excutionOrderList
                    );
                }
                Map<Long, BasicExcutionOrderVO> excutionOrderMap = excutionOrderList.stream().collect(Collectors.toMap(BasicExcutionOrderVO::getId, v -> v));
                dataList.forEach(e -> {
                    if(excutionOrderMap.containsKey(e.getExcuteOrderId())) {
                        BasicExcutionOrderVO basicExcutionOrderVO = excutionOrderMap.get(e.getExcuteOrderId());
                        //e.setCooperateBrandName(basicExcutionOrderVO.getCooperateBrandName());
                        e.setBrandName(basicExcutionOrderVO.getBrandName());
                        e.setBrandNameN(basicExcutionOrderVO.getBrandNameN());
                        e.setProductName(basicExcutionOrderVO.getProductName());
                        e.setCategory(basicExcutionOrderVO.getCategory());
                        e.setCategoryName(basicExcutionOrderVO.getCategoryName());
                        e.setExcutorId(basicExcutionOrderVO.getExcutorId());
                        e.setExcutorName(basicExcutionOrderVO.getExcutorName());
                    }
                });
            }
        }*/
        return dataList;
    }

    @Override
    public List<IncomeContractExportVO> exportContract(IncomeContractSearchDTO contractSearchDTO) {
        contractSearchDTO.setAlias("ic.");
        contractSearchDTO.setProcessIds(ApprovalEnum.getContractProcessIdsWithOfflineCommission());
        if (CollectionUtils.isNotEmpty(contractSearchDTO.getFlowStatus())) {
            List<Long> allList = approvalFlowService.getSrcList(contractSearchDTO.getFlowStatus(), contractSearchDTO.getProcessIds());
            if (CollectionUtils.isEmpty(allList)) {
                return null;
            }
            contractSearchDTO.setSrcIds(allList);
        }
        List<IncomeContractExportVO> exportPage = incomeContractMapper.getExportPage(contractSearchDTO);
        if (CollectionUtils.isNotEmpty(exportPage)) {
            //查询FlowId
            List<Long> idList = exportPage.stream().map(IncomeContractExportVO::getId).collect(Collectors.toList());
            Map<Long, Long> flowMap = approvalFlowService.getNewestFlowIds(idList, ApprovalEnum.getContractProcessIds());
            if (CollectionUtils.isNotEmpty(flowMap)) {
                exportPage.forEach(contract -> {
                    contract.setFlowId(flowMap.get(contract.getId()));
                });
            }
            /**
             * 查询客户名称
             */
            List<Long> customerIdList = exportPage.stream().map(IncomeContractExportVO::getCustomerId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
            Map<Long, BaseCustomer> customerMapping = baseInfoClient.getMcnCustomerByIds(customerIdList).getObj();

            //审批名称
            List<Long> flowList = exportPage.stream().map(IncomeContractExportVO::getFlowId).filter(Objects::nonNull).collect(Collectors.toList());
            JSONObject jsonObject = approvalFlowService.getFlowStatus(flowList);
            //查询项目PM
            List<Long> pmIdList = exportPage.stream().map(IncomeContractExportVO::getPmId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
            if(CollectionUtils.isNotEmpty(pmIdList)) {
                List<SUser> sUserList = privilegeClient.getUserByIds(pmIdList).getObj();
                Map<Long, String> sUserNameMap = CommonUtil.getIfNecessary(CollectionUtils.isNotEmpty(sUserList),
                        () -> sUserList.stream().collect(Collectors.toMap(k -> k.getUserId(), v -> v.getUsername())), Collections.EMPTY_MAP);
                exportPage.forEach(contract -> {
                    contract.setPmName(sUserNameMap.get(contract.getPmId()));
                });
            }
            //查询红人平台信息
            List<Long> starPlatformInfoIds = exportPage.stream().map(IncomeContractExportVO::getStarPlatformInfoId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
            Map<Long, String> starPlatformInfoMap = CommonUtil.getIfNecessary(CollectionUtils.isNotEmpty(starPlatformInfoIds), () -> CommonUtil.defaultList(starPlatformInfoService.selectBatchIds(starPlatformInfoIds)).stream()
                    .collect(Collectors.toMap(k -> k.getId(), v -> StringUtils.joinWith(SeparatorCst.MINUS, v.getPlatNickName(), v.getPlatformName()))), Collections.EMPTY_MAP);
            //品牌信息
            List<String> brandCodes = exportPage.stream().map(IncomeContractExportVO::getCooperateBrand).filter(Objects::nonNull).distinct().collect(Collectors.toList());
            Map<String,String> brandMap = brandInfoService.getBrandMapByCodes(brandCodes);
            //部门信息
            List<Long> departmentIdList = exportPage.stream().map(IncomeContractExportVO::getDepartmentId).collect(Collectors.toList());
            Map<Long, SDepartment> sDepartmentMap = Objects.requireNonNull(privilegeClient.getDepartmentByIds(departmentIdList)).getObj();
            //查询财务已开票金额
            /*List<String> contractCodeList = exportPage.stream().filter(e -> ApprovalStatusEnum.isPassed(e.getApprovalStatus())).map(IncomeContractExportVO::getContractCode).collect(Collectors.toList());
            Map<String, BigDecimal> invoicedAmountMap = CommonUtil.getIfNecessary(CollectionUtils.isNotEmpty(contractCodeList), () ->
                    CommonUtil.defaultList(financeClient.summaryInvoicedAmount(contractCodeList).getObj()).stream()
                     .collect(Collectors.toMap(SummaryInvoicedAmountVO::getChargeSourceCode, SummaryInvoicedAmountVO::getInvoicedAmount)),
                    Collections.EMPTY_MAP);*/
            exportPage.forEach(contract -> {
                if(CommonUtil.containsKey(customerMapping, contract.getCustomerId())) {
                    contract.setCustomerName(customerMapping.get(contract.getCustomerId()).getCustomerNameC());
                }
                if(Objects.nonNull(contract.getStarPlatformInfoId())) {
                    contract.setAnchorName(starPlatformInfoMap.get(contract.getStarPlatformInfoId()));
                }
                contract.setFlowStatusName(CommonUtil.defaultString(jsonObject, contract.getFlowId()));
                if (Objects.nonNull(contract.getDepartmentId())) {
                    if (Objects.nonNull(sDepartmentMap)) {
                        contract.setDepartment(Objects.nonNull(sDepartmentMap.get(contract.getDepartmentId())) ? sDepartmentMap.get(contract.getDepartmentId()).getDepartmentName() : "");
                    }
                }
                if(brandMap.containsKey(contract.getCooperateBrand())) {
                    contract.setCooperateBrandName(brandMap.get(contract.getCooperateBrand()));
                }
                if(NumberCst.ZERO.equals(contract.getIsRoi())) {
                    contract.setRoiRate(McnConstant.NO);
                } else if(NumberCst.ONE.equals(contract.getIsRoi())) {
                    contract.setRoiRate(McnConstant.ROI_PREFIX + contract.getRoiRate());
                } else {
                    contract.setRoiRate(null);
                }
            });
            //字典翻译
            DictTranslationUtils.translation(() -> DictStream.of(
                    DictStream.map(DictTypeCst.SOURCE_OF_CONTRACT, IncomeContractExportVO::getCooperateSource, IncomeContractExportVO::setCooperateSource),
                    DictStream.map(DictTypeCst.FORMAL_CONTRACT, IncomeContractExportVO::getFormalContractType, IncomeContractExportVO::setFormalContractType),
                    DictStream.map(DictTypeCst.COOPERATION_TYPE, IncomeContractExportVO::getCooperationType, IncomeContractExportVO::setCooperationType),
                    DictStream.map(DictTypeCst.ACTIVE_PLATFORMS, IncomeContractExportVO::getLivePlatform, IncomeContractExportVO::setLivePlatform),
                    DictStream.map(DictTypeCst.LIVE_CONTRACT_CATEGORY, IncomeContractExportVO::getLiveContractCategory, IncomeContractExportVO::setLiveContractCategory),
                    DictStream.map(DictTypeCst.INCOME_CONTRACT_TAG, IncomeContractExportVO::getContractTag, IncomeContractExportVO::setContractTag)
                    ),(dictProfileList, dictList) -> baseInfoClient.getDescByCode(new DescByCodeDTO().setDictsCodes(dictList).setProfileCodes(dictProfileList)).getObj(),
                    exportPage
            );
        }
        return exportPage;
    }

    @Override
    public List<LiveContractExportVO> exportLiveContract(IncomeContractSearchDTO contractSearchDTO) {
        contractSearchDTO.setAlias("ic.");
        contractSearchDTO.setProcessIds(ApprovalEnum.getContractProcessIdsWithOfflineCommission());
        if (CollectionUtils.isNotEmpty(contractSearchDTO.getFlowStatus())) {
            List<Long> allList = approvalFlowService.getSrcList(contractSearchDTO.getFlowStatus(), contractSearchDTO.getProcessIds());
            if (CollectionUtils.isEmpty(allList)) {
                return null;
            }
            contractSearchDTO.setSrcIds(allList);
        }
        List<LiveContractExportVO> exportPage = incomeContractMapper.exportLiveContract(contractSearchDTO);
        if (CollectionUtils.isNotEmpty(exportPage)) {
            //查询FlowId
            List<Long> idList = exportPage.stream().map(LiveContractExportVO::getId).collect(Collectors.toList());
            Map<Long, Long> flowMap = approvalFlowService.getNewestFlowIds(idList, Arrays.asList(ApprovalEnum.INCOME_LIVE_CONTRACT.getProcessId()));
            if (CollectionUtils.isNotEmpty(flowMap)) {
                exportPage.forEach(contract -> {
                    contract.setFlowId(flowMap.get(contract.getId()));
                });
            }
            /**
             * 查询客户名称
             */
            List<Long> customerIdList = exportPage.stream().map(LiveContractExportVO::getCustomerId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
            Map<Long, BaseCustomer> customerMapping = Objects.requireNonNull(baseInfoClient.getMcnCustomerByIds(customerIdList)).getObj();

            //审批名称
            List<Long> flowList = exportPage.stream().map(LiveContractExportVO::getFlowId).filter(Objects::nonNull).collect(Collectors.toList());
            JSONObject jsonObject = approvalFlowService.getFlowStatus(flowList);

            List<Long> starPlatformInfoIds = exportPage.stream().map(LiveContractExportVO::getStarPlatformInfoId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
            Map<Long, String> starPlatformInfoMap = CommonUtil.getIfNecessary(CollectionUtils.isNotEmpty(starPlatformInfoIds), () -> CommonUtil.defaultList(starPlatformInfoService.selectBatchIds(starPlatformInfoIds)).stream()
                    .collect(Collectors.toMap(k -> k.getId(), v -> StringUtils.joinWith(SeparatorCst.MINUS, v.getPlatNickName(), v.getPlatformName()))), Collections.EMPTY_MAP);
            /**
             * 查询数据字典
             */
            List<String> brandCodes = exportPage.stream().map(LiveContractExportVO::getCooperateBrand).filter(Objects::nonNull).distinct().collect(Collectors.toList());
            Map<String,String> brandMap = brandInfoService.getBrandMapByCodes(brandCodes);
            List<Long> departmentIdList = exportPage.stream().map(LiveContractExportVO::getDepartmentId).collect(Collectors.toList());
            Map<Long, SDepartment> sDepartmentMap = Objects.requireNonNull(privilegeClient.getDepartmentByIds(departmentIdList)).getObj();
            exportPage.forEach(contract -> {
                if(brandMap.containsKey(contract.getCooperateBrand())) {
                    contract.setCooperateBrand(brandMap.get(contract.getCooperateBrand()));
                }
                contract.setCustomerName(Objects.nonNull(customerMapping.get(contract.getCustomerId())) ? customerMapping.get(contract.getCustomerId()).getCustomerNameC() : "");
                if(Objects.nonNull(contract.getStarPlatformInfoId())) {
                    contract.setAnchorName(starPlatformInfoMap.get(contract.getStarPlatformInfoId()));
                }
                contract.setFlowStatusName(CommonUtil.defaultString(jsonObject, contract.getFlowId()));
                if (Objects.nonNull(contract.getDepartmentId())) {
                    if (Objects.nonNull(sDepartmentMap)) {
                        contract.setDepartment(Objects.nonNull(sDepartmentMap.get(contract.getDepartmentId())) ? sDepartmentMap.get(contract.getDepartmentId()).getDepartmentName() : "");
                    }
                }
                if(NumberCst.ZERO.equals(contract.getIsRoi())) {
                    contract.setRoiRate(McnConstant.NO);
                } else if(NumberCst.ONE.equals(contract.getIsRoi())) {
                    contract.setRoiRate(McnConstant.ROI_PREFIX + contract.getRoiRate());
                } else {
                    contract.setRoiRate(null);
                }
            });
        }
        return exportPage;
    }

    @Override
    public List<IncomeContractAgreementExportVO> exportAgreement(IncomeContractSearchDTO contractSearchDTO) {
        contractSearchDTO.setAlias("ic.");
        contractSearchDTO.setProcessIds(ApprovalEnum.getContractAgreementProcessIds());
        if (CollectionUtils.isNotEmpty(contractSearchDTO.getFlowStatus())) {
            List<Long> allList = approvalFlowService.getSrcList(contractSearchDTO.getFlowStatus(), contractSearchDTO.getProcessIds());
            if (CollectionUtils.isEmpty(allList)) {
                return null;
            }
            contractSearchDTO.setSrcIds(allList);
        }
        List<IncomeContractAgreementExportVO> exportPage = incomeContractMapper.getExportAgreementPage(contractSearchDTO);
        if (CollectionUtils.isNotEmpty(exportPage)) {

            //查询FlowId
            List<Long> idList = exportPage.stream().map(IncomeContractAgreementExportVO::getId).collect(Collectors.toList());
            Map<Long, Long> flowMap = approvalFlowService.getNewestFlowIds(idList, ApprovalEnum.getContractAgreementProcessIds());
            if (CollectionUtils.isNotEmpty(flowMap)) {
                exportPage.forEach(agreement -> {
                    agreement.setFlowId(flowMap.get(agreement.getId()));
                });
            }
            //审批名称
            List<Long> flowList = exportPage.stream().map(IncomeContractAgreementExportVO::getFlowId).filter(Objects::nonNull).collect(Collectors.toList());
            JSONObject jsonObject = approvalFlowService.getFlowStatus(flowList);
            exportPage.forEach(agreement -> {
                List<Integer> changeContentList = JSONObject.parseArray(agreement.getChangeContent(), Integer.class);
                String changeContentString = changeContentList.stream().map(a -> Objects.requireNonNull(AgreementChangeContentEnum.getByType(a)).getDesc()).collect(Collectors.joining(","));
                agreement.setChangeContent(changeContentString);
                agreement.setFlowStatus(CommonUtil.defaultString(jsonObject, agreement.getFlowId()));
            });
        }
        return exportPage;
    }

    @SuppressWarnings("AlibabaAvoidComplexCondition")
    private void validateStatus(IncomeContract incomeContract, Integer status) {
        if (incomeContract.getApprovalStatus() == ApprovalStatusEnum.UN_COMMIT.getCode() &&
                (status != ApprovalStatusEnum.APPROVAL.getCode() && status != ApprovalStatusEnum.INVALID.getCode())) {
            throw new BusinessException(McnErrorCode.DISCOUNT_APPROVAL_UN_COMMIT_COMMIT_ERROR);
        }
        if (incomeContract.getApprovalStatus() == ApprovalStatusEnum.APPROVAL.getCode() &&
                (status != ApprovalStatusEnum.CANCEL.getCode() && status != ApprovalStatusEnum.INVALID.getCode())) {
            throw new BusinessException(McnErrorCode.DISCOUNT_APPROVAL_UN_COMMIT_CANCEL_ERROR);
        }
        if (incomeContract.getApprovalStatus() == ApprovalStatusEnum.PASSED.getCode() &&
                (status != ApprovalStatusEnum.INVALID.getCode())) {
            throw new BusinessException(McnErrorCode.DISCOUNT_APPROVA_PASSED_ERROR);
        }
        if (incomeContract.getApprovalStatus() == ApprovalStatusEnum.REJECTED.getCode() &&
                (status != ApprovalStatusEnum.APPROVAL.getCode() && status != ApprovalStatusEnum.INVALID.getCode())) {
            throw new BusinessException(McnErrorCode.DISCOUNT_APPROVAL_REJECTED_ERROR);
        }
        if (incomeContract.getApprovalStatus() == ApprovalStatusEnum.CANCEL.getCode() &&
                (status != ApprovalStatusEnum.APPROVAL.getCode() && status != ApprovalStatusEnum.INVALID.getCode())) {
            throw new BusinessException(McnErrorCode.DISCOUNT_APPROVAL_CANCEL_ERROR);
        }

    }

    /**
     * 修改收入合同-单据状态
     *
     * @param incomeContractId
     * @param approvalStatus
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean changeStatus(Long incomeContractId, Integer approvalStatus) {
        IncomeContract incomeContract = incomeContractMapper.selectById(incomeContractId);
        BusinessAssert.notNull(incomeContract, McnErrorCode.INCOME_NOT_EXISTS);
        //判断收入合同原审批状态
        BusinessAssert.isTrue(!ApprovalStatusEnum.isInvalid(incomeContract.getApprovalStatus()), McnErrorCode.INCOME_INVALID);
        if (ApprovalStatusEnum.anyMatch(approvalStatus, ApprovalStatusEnum.PASSED, ApprovalStatusEnum.REJECTED)) {
            BusinessAssert.isTrue(!ApprovalStatusEnum.isCancel(incomeContract.getApprovalStatus()), McnErrorCode.INCOME_CANCELED);
        }
        validateStatus(incomeContract, approvalStatus);
        Long departmentHeaderId = null;
        String departmentHeaderName = null;
        //作废收入合同
        if (ApprovalStatusEnum.isInvalid(approvalStatus)) {
            List<IncomeContractAgreementVO> list = incomeContractMapper.selectByIncomeContractId(incomeContractId);
            if (CollectionUtils.isNotEmpty(list)) {
                List<Integer> collect = list.stream().map(IncomeContractAgreementVO::getApprovalStatus).distinct().collect(Collectors.toList());
                boolean match = collect.stream().allMatch(x -> x == ApprovalStatusEnum.INVALID.code());
                BusinessAssert.isTrue(match, McnErrorCode.INCOME_VOID_FAILED);
            }
            List<ContractExcutionOrder> excutionOrderList = contractExcutionOrderMapper.selectList(Wrappers.lambdaQuery(ContractExcutionOrder.class)
                    .eq(ContractExcutionOrder::getIncomeContractId, incomeContractId).eq(ContractExcutionOrder::getIsDelete, NumberCst.ZERO));
            if (CollectionUtils.isNotEmpty(excutionOrderList)) {
                //待提交状态-直接作废关联的执行单
                if(ApprovalStatusEnum.isUnCommit(incomeContract.getApprovalStatus())) {
                    excutionOrderList.stream().filter(x -> !ApprovalStatusEnum.isInvalid(x.getApprovalStatus())).forEach(e -> {
                        ExcutionOrderChangeStatusDTO statusDTO = new ExcutionOrderChangeStatusDTO();
                        statusDTO.setExcutionOrderId(e.getId());
                        statusDTO.setApprovalStatus(ExcutionApprovalStatusEnum.INVALID.code());
                        contractExcutionOrderService.changeStatus(statusDTO, true);
                    });
                } else {
                    List<Integer> collect = excutionOrderList.stream().map(ContractExcutionOrder::getApprovalStatus).distinct().collect(Collectors.toList());
                    boolean match = collect.stream().allMatch(x -> x == ApprovalStatusEnum.INVALID.code());
                    BusinessAssert.isTrue(match, McnErrorCode.EXECUTION_INVALID_FAIL);
                }
            }
            //原合同是否已审批通过
            if (ApprovalStatusEnum.isPassed(incomeContract.getApprovalStatus())) {
                //判断该单据是否能在财务模块费用表查询到非删除状态的费用
                Integer relatedCount = financeClient.getInvalid(incomeContract.getContractCode(), null, null).getObj();
                BusinessAssert.isTrue(relatedCount <= 0, McnErrorCode.INVALID_FAILED);
            }
            //解除意向单关联
            intentionOrderMapper.updateByNoStrategy(Wrappers.lambdaUpdate(DocIntentionOrder.class)
                    .eq(DocIntentionOrder::getIncomeContractId, incomeContract.getId())
                    .set(DocIntentionOrder::getIncomeContractId, null)
                    .set(DocIntentionOrder::getIncomeContractCode, null)
                    .set(DocIntentionOrder::getExcutionOrderId, null)
                    .set(DocIntentionOrder::getExcutionOrderCode, null)
                    .set(DocIntentionOrder::getUpdateBy, UserVoContextHolder.getUserId())
                    .set(DocIntentionOrder::getUpdateName, UserVoContextHolder.getUserName())
                    .set(DocIntentionOrder::getUpdateDate, new Date()));
            //作废-释放直播合同关联的直播商品
            if (IncomeContractTypeEnum.isLiveContract(incomeContract.getContractType())) {
                liveContractCommodityMapper.updateByNoStrategy(Wrappers.lambdaUpdate(LiveContractCommodity.class)
                        .eq(LiveContractCommodity::getIncomeContractId, incomeContract.getId())
                        .set(LiveContractCommodity::getClaimStatus, NumberCst.ZERO)
                        .set(LiveContractCommodity::getIncomeContractId, null)
                        .set(LiveContractCommodity::getIncomeContractCode, null)
                        .set(LiveContractCommodity::getUpdateBy, UserVoContextHolder.getUserId())
                        .set(LiveContractCommodity::getUpdateName, UserVoContextHolder.getUserName())
                        .set(LiveContractCommodity::getUpdateDate, new Date())
                );
            }
        } else if (ApprovalStatusEnum.isApproval(approvalStatus)) {
            List<ContractExcutionOrder> excutionOrders = contractExcutionOrderMapper.selectList(Wrappers.lambdaQuery(ContractExcutionOrder.class)
                    .eq(ContractExcutionOrder::getIncomeContractId, incomeContractId).eq(ContractExcutionOrder::getIsDelete, NumberCst.ZERO)
                    .ne(ContractExcutionOrder::getApprovalStatus, ExcutionApprovalStatusEnum.INVALID.getCode()));
            //校验意向单
            this.verifyIntentionOrder(incomeContract.getContractType(), excutionOrders);
            // 详情页 提交审批
            log.info("打印incomeContract数据集合:{}",JSON.toJSONString(incomeContract));
            this.verifyParams(incomeContract, incomeContractMapper.getPlatformOrderNumber(), excutionOrders);
            UserDTO userDTO = new UserDTO();
            userDTO.setUserId(incomeContract.getCreateBy());
            DepartmentHeadVO departmentHeadVO = privilegeClient.getDepartmentHead(userDTO).getObj();
            if (departmentHeadVO != null && departmentHeadVO.getDepartmentHead() != null) {
                departmentHeaderId = departmentHeadVO.getDepartmentHeadId();
                departmentHeaderName = departmentHeadVO.getDepartmentHead().getUsername();
            }
            //提醒收入合同重复
            this.remindDuplicateEntry(approvalStatus, excutionOrders);
        } else if(ApprovalStatusEnum.isCancel(approvalStatus)) {
            BusinessAssert.isTrue(ApprovalStatusEnum.isApproval(incomeContract.getApprovalStatus()),
                    McnErrorCode.BUSINESS_ERROR, "状态非审批中，不允许撤回！");
        }
        LambdaUpdateWrapper<IncomeContract> lambdaUpdateWrapper = Wrappers.lambdaUpdate(IncomeContract.class).eq(IncomeContract::getId, incomeContractId);
        if(ApprovalStatusEnum.isCancel(approvalStatus) && IncomeContractTypeEnum.isLiveContract(incomeContract.getContractType())) {
            lambdaUpdateWrapper.set(IncomeContract::getOfflineCommissionAmount, null);
        }
        incomeContractMapper.updateByNoStrategy(lambdaUpdateWrapper
                .set(IncomeContract::getDepartmentHeaderId, departmentHeaderId)
                .set(IncomeContract::getDepartmentHeaderName, departmentHeaderName)
                .set(IncomeContract::getApprovalStatus, approvalStatus)
                .set(IncomeContract::getUpdateBy, UserVoContextHolder.getUserId())
                .set(IncomeContract::getUpdateName, UserVoContextHolder.getUserName())
                .set(IncomeContract::getUpdateDate, new Date()));
        ApprovalEnum approvalEnum = ApprovalEnum.getEnumByContractType(incomeContract.getContractType());
        //如果收入合同撤回或作废，则撤回已提起的审批流程
        if (ApprovalStatusEnum.anyMatch(approvalStatus, ApprovalStatusEnum.CANCEL, ApprovalStatusEnum.INVALID)) {
            approvalFlowService.revokeProcess(incomeContract.getId(), approvalEnum.getProcessId());
            // 如果直播合同且线下佣金结算状态-非待结算，则撤回线下佣金结算审批流
            if(IncomeContractTypeEnum.isLiveContract(incomeContract.getContractType())
                    && !OfflineCommissionSettleStatusEnum.isUnsettled(incomeContract.getOfflineCommissionSettleStatus())
                    && ArrayUtils.contains(StringUtils.split(incomeContract.getCooperationType(), SeparatorCst.COMMA), "offlineStraightCommission")) {
                liveContactOfflineCommissionService.invaild(incomeContract.getId());
            }
        }
        if (ApprovalStatusEnum.isApproval(approvalStatus)) {
            if (this.verifyExcutionAmountIfNecessary(incomeContract.getContractType(),
                    incomeContractMapper.confirmedAmount(incomeContract.getId()), incomeContract.getBusinessAmount())) {
                updateExpectedAmount(incomeContract.getId());
            }
            approvalFlowService.startProcess(incomeContract.getId(), incomeContract.getContractCode(), approvalEnum, JSON.toJSONString(incomeContract));
            if (InvoiceFormEnum.needAutoInvoice(incomeContract.getInvoiceForm())) {
                stringRedisTemplate.opsForValue().set(Constant.AUTHORIZATION + ":" + APPROVAL_KEY + incomeContract.getContractCode(), JSONObject.toJSONString(UserVoContextHolder.getUserVo()), 100, TimeUnit.DAYS);
            }
        }
        //操作日志
        EventPublisher.post(OperateLogEvent.builder().businessId(incomeContract.getId())
                .businessType(LogBusinessTypeEnum.INCOME_CONTRACT)
                .actionName(ApprovalStatusEnum.getActionName(approvalStatus))
                .compare(incomeContract, incomeContractMapper.selectById(incomeContract.getId()))
                .build());
        return true;
    }

    @Override
    public BigDecimal getExpectedAmount(Long incomeContractId) {
        List<ContractExcutionOrder> excutionList = contractExcutionOrderMapper.selectList(Wrappers.lambdaQuery(ContractExcutionOrder.class)
                .select(ContractExcutionOrder::getId).eq(ContractExcutionOrder::getIncomeContractId, incomeContractId).eq(ContractExcutionOrder::getIsDelete, NumberCst.ZERO));
        BigDecimal expectedAmount = BigDecimal.ZERO;
        if (CollectionUtils.isNotEmpty(excutionList)) {
            List<Long> excutionOrderIds = excutionList.stream().map(ContractExcutionOrder::getId).collect(Collectors.toList());
            Map<Long, CalculationDevided> cdMap = CommonUtil.defaultList(calculationDevidedMapper.selectList(Wrappers.lambdaQuery(CalculationDevided.class)
                    .in(CalculationDevided::getExcutionOrderId, excutionOrderIds).eq(CalculationDevided::getIsDelete, NumberCst.ZERO))
            ).stream().collect(Collectors.toMap(k -> k.getExcutionOrderId(), Function.identity()));
            try {
                for (ContractExcutionOrder e : excutionList) {
                    BigDecimal sysDevidedAmount = contractExcutionOrderService.getSysDevidedAmount(e, cdMap.get(e.getId()));
                    expectedAmount = expectedAmount.add(ObjectUtils.defaultIfNull(sysDevidedAmount, BigDecimal.ZERO));
                }
            } catch (Exception e) {
                log.error("计算收入合同预估金额异常{}", e);
               return null;
            }
        }
        return expectedAmount;
    }

    private Long saveIncomeContract(IncomeContractAddDTO incomeContractAddDTO) {
        List<ContractExcutionOrder> excutionOrders = incomeContractAddDTO.getExcutionOrders();
        refactorSave(incomeContractAddDTO, excutionOrders);
        performanceSharerDepartmentId(incomeContractAddDTO);
        /**
         * 录入开票信息
         */
        setInvoiceInfo(incomeContractAddDTO);
        if (Objects.isNull(incomeContractAddDTO.getId())) {
            incomeContractAddDTO.setNewestAmount(incomeContractAddDTO.getBusinessAmount());
            incomeContractAddDTO.setContractCode(CodeGenerateHelper.getCode(BillCodeCst.INCOME_CONTRACT));
            verityCustomerFirstOrder(incomeContractAddDTO);
            setDepartmentHead(incomeContractAddDTO, UserVoContextHolder.getUserId());
            //提醒收入合同重复
            this.remindDuplicateEntry(incomeContractAddDTO.getApprovalStatus(), incomeContractAddDTO.getExcutionOrders());
            if (IncomeContractTypeEnum.isLiveContract(incomeContractAddDTO.getContractType())) {
                incomeContractAddDTO.setLiveCommissionSettleStatus(CommonSettleStatusEnum.UNSETTLED.getCode());
            }
            incomeContractMapper.insert(incomeContractAddDTO);
        } else {
            saveVertifyStatus(incomeContractAddDTO.getId());
            refactor2(incomeContractAddDTO);
            //编辑收入合同-同步变更执行单
            contractExcutionOrderService.changeExcutionOrders(incomeContractAddDTO.getId(), excutionOrders);
        }
        if (CollectionUtil.isNotEmpty(excutionOrders)) {
            //填充账号是否入驻
            this.fillInSystemAdmin(excutionOrders);
            Map<Long, BaseCustomer> customerMap = baseInfoClient.getMcnCustomerByIds(Collections.singletonList(incomeContractAddDTO.getCustomerId())).getObj();
            List<ExcuteFeedback> feedbackInsertList = new ArrayList<>();
            List<CalculationDevided> calculationDevidedInsertList = new ArrayList<>();

            //查询执行单红人信息
            List<Long> starIds = excutionOrders.stream().map(x->x.getStarId()).collect(Collectors.toList());
            List<StarBasicData> starBasicDataList= starBasicDataMapper.selectBatchIds(starIds);
            Map<Long, StarBasicData> starBasicDataMap = starBasicDataList.stream().collect(Collectors.toMap(StarBasicData::getId, x -> x, (x, y) -> x));

            //查询红人平台信息
            List<Long> starPlatformInfoIds = excutionOrders.stream().map(x -> x.getStarPlatformInfoId()).collect(Collectors.toList());
            List<StarPlatformInfo> starPlatformInfos = starPlatformInfoService.selectList(new QueryWrapper<StarPlatformInfo>().lambda().in(StarPlatformInfo::getId, starPlatformInfoIds));
            Map<Long, StarPlatformInfo> starPlatformInfoMap = starPlatformInfos.stream().collect(Collectors.toMap(StarPlatformInfo::getId, x -> x, (x, y) -> x));

            //查询客户档案
            Set<Long> customerIds = incomeContractAddDTO.getExcutionOrders().stream().map(x -> x.getCustomerId()).collect(Collectors.toSet());
            Map<Long, BaseCustomer> baseCustomerMap = baseInfoClient.getMcnCustomerByIds(new ArrayList<>(customerIds)).getObj();

            List<String> brandCodes = excutionOrders.stream().map(ContractExcutionOrder::getBrandName).filter(Objects::nonNull).distinct().collect(Collectors.toList());
            Map<String,String> brandMap = brandInfoService.getBrandMapByCodes(brandCodes);
            excutionOrders.forEach(excutionOrder -> {
                StarBasicData starBasicData = starBasicDataMap.get(excutionOrder.getStarId());
                if (Objects.nonNull(starBasicData)) {
                    if (StarTypeEnum.INSIDE.getCode().equals(starBasicData.getStarType())) {
                        excutionOrder.setType(ExcutionOrderTypeEnum.INSIDE_EXCUTION_ORDER.getType());
                    } else if (StarTypeEnum.OUTSIDE.getCode().equals(starBasicData.getStarType())) {
                        excutionOrder.setType(ExcutionOrderTypeEnum.OUTSIDE_EXCUTION_ORDER.getType());
                    } else if (StarTypeEnum.KOC.getCode().equals(starBasicData.getStarType())) {
                        excutionOrder.setType(ExcutionOrderTypeEnum.KOC_EXCUTION_ORDER.getType());
                    }
                }
                StarPlatformInfo starPlatformInfo = starPlatformInfoMap.get(excutionOrder.getStarPlatformInfoId());
                if(Objects.nonNull(starPlatformInfo)){
                    excutionOrder.setPlatformId(starPlatformInfo.getPlatformId());
                }

                if (excutionOrder.getId() == null) {
                    excutionOrder.setExcuteCode(CodeGenerateHelper.getCode(BillCodeCst.EXCUTION_ORDER));
                    excutionOrder.setIncomeContractId(incomeContractAddDTO.getId());
                    excutionOrder.setIncomeContractCode(incomeContractAddDTO.getContractCode());
                    excutionOrder.setApprovalStatus(ExcutionApprovalStatusEnum.UN_EXECUTE.getCode());
                    BaseCustomer customer = baseCustomerMap.get(excutionOrder.getCustomerId());
                    if (Objects.nonNull(customer)) {
                        excutionOrder.setCustomerId(customer.getCustomerId());
                        excutionOrder.setCustomerCode(customer.getCustomerCode());
                    }
                    //执行单总金额默认等于内容实际报价+其他收入+平台手续费/微任务金额+特殊收入
                    //excutionOrder.setBrandName(excutionOrder.getCooperateBrand());

                    excutionOrder.setPlatformOrderCode(excutionOrder.getPlatformOrderNumber());
                    contractExcutionOrderMapper.insert(excutionOrder);
                    saveFeedBack(excutionOrder, feedbackInsertList);
                    //初始化计算分成的客户返点比例、年度返点比例、客户返点金额
                    CalculationDevided calculationDevided = new CalculationDevided();
                    saveCalculationDevided(incomeContractAddDTO.getCustomerId(), incomeContractAddDTO.getDiscountId(), calculationDevided, customerMap, excutionOrder);
                    calculationDevidedInsertList.add(calculationDevided);
                } else {
                    refactor(incomeContractAddDTO, customerMap, brandMap, excutionOrder);
                }
                if(Objects.nonNull(excutionOrder.getIntentionOrderId())) {
                    //更新意向单绑定关系
                    DocIntentionOrder docIntentionOrder = new DocIntentionOrder();
                    docIntentionOrder.setIncomeContractId(incomeContractAddDTO.getId());
                    docIntentionOrder.setIncomeContractCode(incomeContractAddDTO.getContractCode());
                    docIntentionOrder.setExcutionOrderId(excutionOrder.getId());
                    docIntentionOrder.setExcutionOrderCode(excutionOrder.getExcuteCode());
                    docIntentionOrder.setPublishDate(excutionOrder.getPromisePublishDate());
                    docIntentionOrder.setPublishDateEnd(excutionOrder.getPromisePublishDateEnd());
                    docIntentionOrder.setId(excutionOrder.getIntentionOrderId());
                    intentionOrderMapper.updateById(docIntentionOrder);
                }
            });
            if (CollectionUtil.isNotEmpty(feedbackInsertList)) {
                excuteFeedbackMapper.insertBatch(feedbackInsertList);
            }
            if (CollectionUtil.isNotEmpty(calculationDevidedInsertList)) {
                calculationDevidedMapper.insertBatch(calculationDevidedInsertList);
            }
        }
        return incomeContractAddDTO.getId();
    }

    private void saveVertifyStatus(Long id) {
        IncomeContract incomeContract = incomeContractMapper.selectById(id);
        if (incomeContract.getApprovalStatus() != ApprovalStatusEnum.UN_COMMIT.code() &&
                incomeContract.getApprovalStatus() != ApprovalStatusEnum.REJECTED.code() &&
                incomeContract.getApprovalStatus() != ApprovalStatusEnum.CANCEL.code()) {
            throw new BusinessException(McnErrorCode.DISCOUNT_APPROVA_UPDATE_ERROR);
        }
    }

    /**
     * 保存直播合同商品
     * @param incomeContractAddDTO
     */
    // private void saveLiveContractCommodity(IncomeContractAddDTO incomeContractAddDTO) {
    //     List<LiveContractCommodityAddDTO> liveContractCommodityList = incomeContractAddDTO.getLiveContractCommodityList();
    //     BusinessAssert.notEmpty(liveContractCommodityList, McnErrorCode.PARAM_ERROR, "直播合同-商品信息不能为空");
    //     if(Objects.nonNull(incomeContractAddDTO.getLiveDate())) {
    //         String liveDateStr = DateUtils.formatDate(incomeContractAddDTO.getLiveDate(), McnConstant.SHORT_DATE_FORMAT);
    //         List<String> repeatedCommodityIds = liveContractCommodityList.stream()
    //                 .collect(Collectors.groupingBy(LiveContractCommodityAddDTO::getCommodityId, Collectors.counting()))
    //                 .entrySet().stream().filter(e -> e.getValue().longValue() > 1L).map(Map.Entry::getKey).collect(Collectors.toList());
    //         if(CollectionUtils.isNotEmpty(repeatedCommodityIds)) {
    //             throw new BusinessException(McnErrorCode.BUSINESS_ERROR.code(), String.format("该直播日期和主播【%s】下，商品ID【%s】重复！", liveDateStr, StringUtils.join(repeatedCommodityIds, SeparatorCst.VERTICAL_LINE)));
    //         }
    //     }
    //     List<LiveContractCommodity> saveList = liveContractCommodityList.stream().map(e -> {
    //         LiveContractCommodity liveContractCommodity = new LiveContractCommodity();
    //         BeanUtils.copyProperties(e,liveContractCommodity);
    //         liveContractCommodity.setIncomeContractId(incomeContractAddDTO.getId());
    //         liveContractCommodity.setIncomeContractCode(incomeContractAddDTO.getContractCode());
    //         liveContractCommodity.setAnchorId(incomeContractAddDTO.getAnchorId());
    //         liveContractCommodity.setLiveDate(incomeContractAddDTO.getLiveDate());
    //         liveContractCommodity.setCustomerId(incomeContractAddDTO.getCustomerId());
    //         liveContractCommodity.setFranchiserId(UserVoContextHolder.getUserId());
    //         liveContractCommodity.setLivePlatform(incomeContractAddDTO.getLivePlatform());
    //         if(Objects.isNull(e.getId())) {
    //             liveContractCommodity.setCommodityStatus(NumberCst.ONE);
    //         }
    //         liveContractCommodity.setClaimStatus(NumberCst.ONE);
    //         return liveContractCommodity;
    //     }).collect(Collectors.toList());
    //     saveList.forEach(e -> {
    //         if(Objects.nonNull(incomeContractAddDTO.getLiveDate())) {
    //             LiveContractCommodity entity = liveContractCommodityMapper.selectOne(Wrappers.lambdaQuery(LiveContractCommodity.class)
    //                     .eq(LiveContractCommodity::getCommodityId, e.getCommodityId())
    //                     .eq(Objects.nonNull(incomeContractAddDTO.getLiveDate()), LiveContractCommodity::getLiveDate, e.getLiveDate())
    //                     .ne(Objects.nonNull(e.getId()), LiveContractCommodity::getId, e.getId()));
    //             if(Objects.nonNull(entity)) {
    //                 BusinessAssert.isFalse(Objects.equals(entity.getClaimStatus(), NumberCst.ONE), McnErrorCode.BUSINESS_ERROR, "商品已被认领，请检查后重试！");
    //                 e.setId(entity.getId());
    //             }
    //         }
    //     });
    //     List<LiveContractCommodity> insertList = saveList.stream().filter(e -> Objects.isNull(e.getId())).collect(Collectors.toList());
    //     List<LiveContractCommodity> updateList = saveList.stream().filter(e -> Objects.nonNull(e.getId())).collect(Collectors.toList());
    //     if(CollectionUtils.isNotEmpty(insertList)) {
    //         insertList.forEach(e -> e.setSettlementStatus(NumberCst.ZERO));
    //         liveContractCommodityMapper.insertBatch(insertList);
    //     }
    //     if(CollectionUtils.isNotEmpty(updateList)) {
    //         List<Long> idList = updateList.stream().map(LiveContractCommodity::getId).collect(Collectors.toList());
    //         List<LiveContractCommodity> dataList = liveContractCommodityMapper.selectBatchIds(idList);
    //         updateList.forEach(e -> {
    //             Date now = new Date();
    //             liveContractCommodityMapper.updateByNoStrategy(Wrappers.lambdaUpdate(LiveContractCommodity.class)
    //                     .set(LiveContractCommodity::getAnchorId, e.getAnchorId())
    //                     .set(LiveContractCommodity::getLiveDate, e.getLiveDate())
    //                     .set(LiveContractCommodity::getLivePlatform, e.getLivePlatform())
    //                     .set(LiveContractCommodity::getCommodityId, e.getCommodityId())
    //                     .set(LiveContractCommodity::getCommodityName, e.getCommodityName())
    //                     .set(LiveContractCommodity::getClaimStatus, e.getClaimStatus())
    //                     .set(LiveContractCommodity::getCooperateBrand, e.getCooperateBrand())
    //                     .set(LiveContractCommodity::getBrandName, e.getBrandName())
    //                     .set(LiveContractCommodity::getLiveContractCategory, e.getLiveContractCategory())
    //                     .set(LiveContractCommodity::getProductImage, e.getProductImage())
    //                     .set(LiveContractCommodity::getProductLink, e.getProductLink())
    //                     .set(LiveContractCommodity::getOnlineCommissionRate, e.getOnlineCommissionRate())
    //                     .set(LiveContractCommodity::getOfflineCommissionRate, e.getOfflineCommissionRate())
    //                     .set(LiveContractCommodity::getPitFeeAmount, e.getPitFeeAmount())
    //                     .set(LiveContractCommodity::getRoiSales, e.getRoiSales())
    //                     .set(LiveContractCommodity::getRoiRate, e.getRoiRate())
    //                     .set(LiveContractCommodity::getUpdateBy, UserVoContextHolder.getUserId())
    //                     .set(LiveContractCommodity::getUpdateName, UserVoContextHolder.getUserName())
    //                     .set(LiveContractCommodity::getUpdateDate, now)
    //                     .eq(LiveContractCommodity::getId, e.getId())
    //             );
    //         });
    //         Map<Long, LiveContractCommodity> dataMap = CommonUtil.defaultList(liveContractCommodityMapper.selectBatchIds(idList)).stream().collect(Collectors.toMap(k -> k.getId(), Function.identity()));
    //         dataList.forEach(data -> {
    //             EventPublisher.post(OperateLogEvent.builder().bussinessId(data.getId())
    //                     .bussinessType(FieldChangeBussinessTypeEnum.LIVE_COMMODITY.getType())
    //                     .operationType(FieldChangeOperationTypeEnum.UPDATE.getType())
    //                     .compare(() -> data, () -> dataMap.get(data.getId())).build());
    //         });
    //     }
    // }

    /**
     * 校验部门业绩共享人
     *
     * @param incomeContract
     */
    private void performanceSharerDepartmentId(IncomeContract incomeContract) {
        if (Objects.nonNull(incomeContract.getPerformanceSharerId())) {
            List<Long> shareIds = Collections.singletonList(incomeContract.getPerformanceSharerId());
            List<SUserVo> userVos = Objects.requireNonNull(privilegeClient.getDepartmentByUserIds(shareIds)).getObj();
            Map<Long, SUserVo> sUserVoMap = userVos.stream().collect(Collectors.toMap(SUserVo::getUserId, sUserVo -> sUserVo));
            incomeContract.setPerformanceSharerDepartmentId(
                    incomeContract.getPerformanceShare() == 1 ?
                            sUserVoMap.get(incomeContract.getPerformanceSharerId()).getDepartmentId() : null);
        }
    }

    /**
     * 校验新客户首单
     *
     * @param incomeContractAddDTO
     */
    public void verityCustomerFirstOrder(IncomeContractAddDTO incomeContractAddDTO) {
        List<IncomeContract> incomeContracts = incomeContractMapper.selectList(Wrappers.lambdaQuery(IncomeContract.class)
                .eq(IncomeContract::getCustomerId, incomeContractAddDTO.getCustomerId())
                .eq(IncomeContract::getIsDelete, Boolean.FALSE)
                .ne(IncomeContract::getApprovalStatus, ApprovalStatusEnum.INVALID.code()));
        if (CollectionUtils.isEmpty(incomeContracts)) {
            incomeContractAddDTO.setCustomerFirstOrder(Boolean.TRUE);
            return;
        }
        List<Boolean> list = incomeContracts.stream().filter(o -> Objects.isNull(incomeContractAddDTO.getId())
                || o.getId().longValue() != incomeContractAddDTO.getId().longValue())
                .map(IncomeContract::getCustomerFirstOrder).distinct().collect(Collectors.toList());
        incomeContractAddDTO.setCustomerFirstOrder(CollectionUtils.isEmpty(list) || !list.contains(Boolean.TRUE));
    }


    private void refactorSave(IncomeContractAddDTO incomeContractAddDTO, List<ContractExcutionOrder> excutionOrders) {
        incomeContractAddDTO.setPayBackAmount(BigDecimal.ZERO);
        incomeContractAddDTO.setPayBackDate(null);
        incomeContractAddDTO.setPayBackStatus(NumberCst.ZERO);
        Integer performanceShare = incomeContractAddDTO.getPerformanceShare();
        if (performanceShare != null && performanceShare.equals(0)) {
            incomeContractAddDTO.setPerformanceSharerId(null);
            incomeContractAddDTO.setPerformanceSharerName(null);
        }
        if (incomeContractAddDTO.getDiscountId() == null) {
            incomeContractAddDTO.setDiscountCode(null);
            incomeContractAddDTO.setDiscountRate(null);
        }
        if (CollectionUtils.isEmpty(excutionOrders)) {
            return;
        }
        boolean isFromExcutionOrder = ObjectUtils.defaultIfNull(incomeContractAddDTO.getIsFromExcutionOrder(), Boolean.FALSE).booleanValue();
        contractExcutionOrderService.verifyFormalExcutionOrder(incomeContractAddDTO.getId(), isFromExcutionOrder, excutionOrders);
        //校验意向单
        this.verifyIntentionOrder(incomeContractAddDTO.getContractType(), excutionOrders);
    }

    /**
     * 校验意向单
     * @param contractType
     * @param excutionOrders
     */
    private void verifyIntentionOrder(Integer contractType, List<ContractExcutionOrder> excutionOrders) {
        if(CollectionUtils.isEmpty(excutionOrders)) {
            return;
        }
        //校验关联意向单
        List<Long> intentionOrderIds = excutionOrders.stream().filter(e -> !ExcutionApprovalStatusEnum.isInvalid(e.getApprovalStatus()))
                .map(ContractExcutionOrder::getIntentionOrderId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(intentionOrderIds)) {
            Integer count = intentionOrderMapper.selectCount(Wrappers.lambdaQuery(DocIntentionOrder.class)
                    .in(DocIntentionOrder::getId, intentionOrderIds)
                    .in(DocIntentionOrder::getStatus, Arrays.asList(IntentionOrderStatusEnum.CONRIMED.getCode(),IntentionOrderStatusEnum.EXECUTING.getCode(), IntentionOrderStatusEnum.EXECUTED.getCode()))
                    .eq(DocIntentionOrder::getIsDelete, NumberCst.ZERO));
            BusinessAssert.isTrue(count > 0, McnErrorCode.INCOME_ADD_INTENTION_ORDER_ERROR);
            if(IncomeContractTypeEnum.isFormalContract(contractType)) {
                BusinessAssert.isTrue(count == 1, McnErrorCode.FORMAL_INCOME_ONE_INTENTION_ORDER);
            }
        }
    }

    private void refactor2(IncomeContractAddDTO incomeContractAddDTO) {
        IncomeContract incomeContract = incomeContractMapper.selectById(incomeContractAddDTO.getId());
        incomeContractAddDTO.setContractCode(incomeContract.getContractCode());
        IncomeContract afterContract = new IncomeContract();
        incomeContractAddDTO.setCreateBy(incomeContract.getCreateBy());
        incomeContractAddDTO.setCreateName(incomeContract.getCreateName());
        BeanUtils.copyProperties(incomeContractAddDTO, afterContract);
        setDepartmentHead(incomeContractAddDTO, incomeContract.getCreateBy());
        UserVO userVO = UserVoContextHolder.getUserVo();
        incomeContractAddDTO.setUpdateBy(userVO.getUserId());
        incomeContractAddDTO.setUpdateName(userVO.getRealName());
        incomeContractAddDTO.setUpdateDate(new Date());
        verityCustomerFirstOrder(incomeContractAddDTO);
        //提醒收入合同重复
        this.remindDuplicateEntry(incomeContractAddDTO.getApprovalStatus(), incomeContractAddDTO.getExcutionOrders());
        /**注：塞值无效提示-incomeContractAddDTO（禁止继承Entity)创建人信息会做拦截保护不允许更新、修改人信息拦截会自动填充 */
        incomeContractMapper.updateIncomeContract(incomeContractAddDTO);

        //操作日志
        EventPublisher.post(OperateLogEvent.builder().businessId(incomeContract.getId())
                .businessType(LogBusinessTypeEnum.INCOME_CONTRACT)
                .compare(incomeContract, incomeContractMapper.selectById(incomeContract.getId()))
                .build());
    }


    private void refactor(IncomeContractAddDTO incomeContractAddDTO, Map<Long, BaseCustomer> customerMap, Map<String,String> brandMap, ContractExcutionOrder excutionOrder) {
        excutionOrder.setPlatformOrderCode(excutionOrder.getPlatformOrderNumber());
        ContractExcutionOrder beforeOrder = contractExcutionOrderMapper.selectById(excutionOrder.getId());
        contractExcutionOrderMapper.updateById(excutionOrder);

        CalculationDevided calculationDevided = calculationDevidedMapper.selectOne(Wrappers.lambdaQuery(CalculationDevided.class).eq(CalculationDevided::getExcutionOrderId, excutionOrder.getId()));
        saveCalculationDevided(incomeContractAddDTO.getCustomerId(), incomeContractAddDTO.getDiscountId(), calculationDevided, customerMap, excutionOrder);
        calculationDevidedMapper.updateById(calculationDevided);
        //操作日志
        EventPublisher.post(OperateLogEvent.builder().businessId(beforeOrder.getId())
                .businessType(LogBusinessTypeEnum.EXECUTION_ORDER)
                .compare(beforeOrder, contractExcutionOrderMapper.selectById(excutionOrder.getId()))
                .build());
    }

    private void setDepartmentHead(IncomeContractAddDTO incomeContractAddDTO, Long userId) {
        if (ApprovalStatusEnum.isApproval(incomeContractAddDTO.getApprovalStatus())) {
            UserDTO userDTO = new UserDTO();
            userDTO.setUserId(userId);
            DepartmentHeadVO departmentHeadVO = privilegeClient.getDepartmentHead(userDTO).getObj();
            if (departmentHeadVO != null && departmentHeadVO.getDepartmentHead() != null) {
                incomeContractAddDTO.setDepartmentHeaderId(departmentHeadVO.getDepartmentHeadId());
                incomeContractAddDTO.setDepartmentHeaderName(departmentHeadVO.getDepartmentHead().getUsername());
            }
        }
    }

    @Override
    public void saveFeedBack(ContractExcutionOrder excutionOrder, List<ExcuteFeedback> feedbackInsertList) {
        ExcuteFeedback excuteFeedback = new ExcuteFeedback();
        excuteFeedback.setExcutionOrderId(excutionOrder.getId());
        excuteFeedback.setExcutionOrderCode(excutionOrder.getExcuteCode());
        feedbackInsertList.add(excuteFeedback);
    }

    @Override
    public CalculationDevided saveCalculationDevided(Long customerId, Long discountId, CalculationDevided calculationDevided, Map<Long, BaseCustomer> customerMap, ContractExcutionOrder excutionOrder) {
        boolean hasCustomerRebateRate = discountId == null && Boolean.TRUE.equals(excutionOrder.getPlatformReport()) && ExcutionOrderTypeEnum.isInside(excutionOrder.getType());
//        BigDecimal customerRebateRate = null;
//        if (hasCustomerRebateRate) {
//            customerRebateRate = Optional.ofNullable(excutionOrder.getCustomerRebateRate()).orElse(BigDecimal.ZERO);
//        } else {
//            customerRebateRate = contractExcutionOrderService.getCustomerRebateRate(excutionOrder);
//        }
        //calculationDevided.setCustomerRebateRate(customerRebateRate);
        calculationDevided.setAeCustomerRabateRate(excutionOrder.getAeCustomerRabateRate());
/*        if(Objects.isNull(calculationDevided.getId())) {
            DevidedAmountDTO devidedAmountDTO = new DevidedAmountDTO();
            devidedAmountDTO.setExcutionOrderId(excutionOrder.getId());
            devidedAmountDTO.setAeCustomerRabateRate(calculationDevided.getAeCustomerRabateRate());
            BigDecimal sysDevidedAmount = contractExcutionOrderService.getSysDevidedAmount(devidedAmountDTO, excutionOrder);
            calculationDevided.setSysDevidedAmount(sysDevidedAmount);
        } else {
            DevidedAmountDTO devidedAmountDTO = new DevidedAmountDTO();
            devidedAmountDTO.setExcutionOrderId(excutionOrder.getId());
            calculationDevided.setSysDevidedAmount(contractExcutionOrderService.getSysDevidedAmount(devidedAmountDTO, excutionOrder));
        }*/
        if (customerMap.get(customerId).getFixedRebateRatio() == null) {
            BigDecimal yearRebateRate = contractExcutionOrderService.getYearRebateRate(excutionOrder);
            calculationDevided.setYearRebateRate(yearRebateRate);
        }
        if (excutionOrder.getActualQuotedPrice() != null && calculationDevided.getCustomerRebateRate() != null) {
            calculationDevided.setCustomerRebateAmount(excutionOrder.getActualQuotedPrice()
                    .multiply(calculationDevided.getCustomerRebateRate().divide(BigDecimal.valueOf(100))));
        }

        calculationDevided.setExcutionOrderId(excutionOrder.getId());
        calculationDevided.setExcutionOrderCode(excutionOrder.getExcuteCode());
        calculationDevided.setAeCustomerRabateAmount(excutionOrder.getAeCustomerRabateAmount());
        if(CommonUtil.greaterThanZero(excutionOrder.getCardRatePrice())) {
            BigDecimal diffAmount = excutionOrder.getCardRatePrice().subtract(ObjectUtils.defaultIfNull(excutionOrder.getRealAmount(), BigDecimal.ZERO))
                    .add(ObjectUtils.defaultIfNull(excutionOrder.getAeCustomerRabateAmount(), BigDecimal.ZERO));
            BigDecimal actualDiscountRatio = diffAmount.multiply(McnConstant.ONE_HUNDRED).divide(excutionOrder.getCardRatePrice(), 2, BigDecimal.ROUND_HALF_UP);
            calculationDevided.setActualDiscountRatio(actualDiscountRatio);
        }
        return calculationDevided;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean refreshCalculationDevided() {
        List<ContractExcutionOrder> excutionOrders = calculationDevidedMapper.refreshCalculationDevided();
        List<Long> incomeContractIds = excutionOrders.stream().map(ContractExcutionOrder::getIncomeContractId).collect(Collectors.toList());
        List<IncomeContract> incomeContractList = incomeContractMapper.selectBatchIds(incomeContractIds);
        List<Long> dbContractIds = incomeContractList.stream().map(IncomeContract::getId).collect(Collectors.toList());
        Map<Long, Long> customerIdMap = incomeContractList.stream().collect(Collectors.toMap(IncomeContract::getId, IncomeContract::getCustomerId));

        List<Long> customerIds = incomeContractList.stream().map(IncomeContract::getCustomerId).collect(Collectors.toList());
        Map<Long, BaseCustomer> customerMap = baseInfoClient.getMcnCustomerByIds(customerIds).getObj();

        List<CalculationDevided> calculationDevidedList = new ArrayList<>();
        for (ContractExcutionOrder excutionOrder : excutionOrders) {
            if (!dbContractIds.contains(excutionOrder.getIncomeContractId())) {
                continue;
            }
            CalculationDevided calculationDevided = new CalculationDevided();
//            BigDecimal customerRebateRate = contractExcutionOrderService.getCustomerRebateRate(excutionOrder);
//            calculationDevided.setCustomerRebateRate(customerRebateRate);
            Long incomeContractId = excutionOrder.getIncomeContractId();
            if (customerIdMap.containsKey(incomeContractId)) {
                Long customerId = customerIdMap.get(incomeContractId);
                if (customerMap.get(customerId).getFixedRebateRatio() == null) {
                    BigDecimal yearRebateRate = contractExcutionOrderService.getYearRebateRate(excutionOrder);
                    calculationDevided.setYearRebateRate(yearRebateRate);
                }
            }
            if (excutionOrder.getActualQuotedPrice() != null && calculationDevided.getCustomerRebateRate() != null) {
                calculationDevided.setCustomerRebateAmount(excutionOrder.getActualQuotedPrice()
                        .multiply(calculationDevided.getCustomerRebateRate().divide(BigDecimal.valueOf(100))));
            }
            calculationDevided.setExcutionOrderId(excutionOrder.getId());
            calculationDevided.setExcutionOrderCode(excutionOrder.getExcuteCode());
            calculationDevided.setCreateBy(excutionOrder.getCreateBy());
            calculationDevided.setCreateName(excutionOrder.getCreateName());
            calculationDevided.setCreateDate(excutionOrder.getCreateDate());
            calculationDevided.setUpdateBy(excutionOrder.getUpdateBy());
            calculationDevided.setUpdateName(excutionOrder.getUpdateName());
            calculationDevided.setUpdateDate(excutionOrder.getUpdateDate());
            calculationDevidedList.add(calculationDevided);
        }
        return calculationDevidedMapper.insertBatch(calculationDevidedList) > 0;
    }

    private void setInvoiceInfo(IncomeContractAddDTO incomeContractAddDTO) {
        if (Objects.isNull(incomeContractAddDTO.getContractType())) {
            return;
        }
        Integer contractType = incomeContractAddDTO.getContractType();
        IncomeContractTypeEnum contractTypeEnum = IncomeContractTypeEnum.getType(contractType);
        switch (contractTypeEnum) {
            case SINGLE_ORDERS_FORMAL_CONSTRACT:
            case ANNUAL_DISCOUNT_FORMAL_CONSTRACT:
            case ANNNUAL_DISCOUNT_INCOME_CONSTRACT:
            case SINGLE_ORDERS_INCOME_CONSTRACT:
                incomeContractAddDTO.setAdAmount(incomeContractAddDTO.getBusinessAmount());
                incomeContractAddDTO.setLiveAmount(BigDecimal.ZERO);
                break;
            default:
                break;
        }

        switch (contractTypeEnum) {
            case SINGLE_ORDERS_FORMAL_CONSTRACT:
            case ANNUAL_DISCOUNT_FORMAL_CONSTRACT:
                incomeContractAddDTO.setInvoiceForm(InvoiceFormEnum.NO_NEED_INVOICE.getType());
                incomeContractAddDTO.setInvoiceType("");
                incomeContractAddDTO.setInvoiceContent("");
                incomeContractAddDTO.setInvoiceRemark("");
                //addSingleBilling(baseCustomer.getCustomerCode(), baseCustomer.getCustomerNameC(), incomeContractAddDTO);
                break;
            case ANNNUAL_DISCOUNT_INCOME_CONSTRACT:
            case SINGLE_ORDERS_INCOME_CONSTRACT:
            case LIVE_CONTRACT:
                if (InvoiceFormEnum.NO_NEED_INVOICE.getType().equals(incomeContractAddDTO.getInvoiceForm())) {
                    incomeContractAddDTO.setInvoiceType("");
                    incomeContractAddDTO.setInvoiceContent("");
                    incomeContractAddDTO.setInvoiceRemark("");
                    //addSingleBilling(baseCustomer.getCustomerCode(), baseCustomer.getCustomerNameC(), incomeContractAddDTO);
                }
                break;
            default:
                break;
        }
    }

    @Deprecated
    private void addSingleBilling(String customerCode, String customerName, IncomeContractAddDTO incomeContractAddDTO) {
        if (StringUtils.isBlank(incomeContractAddDTO.getCustomerSignSubject())) {
            incomeContractAddDTO.setCustomerBillingId(null);
            return;
        }

        if (Objects.nonNull(incomeContractAddDTO.getCustomerBillingId())) {
            return;
        }

        BaseCustomerBillingVO originBilling = baseInfoClient.getDefaultBillings(customerCode, customerName).getObj();
        if (originBilling == null) {
            String defaultValue = "000000";
            BaseCustomerBillingVO baseCustomerBillingVO = new BaseCustomerBillingVO();
            baseCustomerBillingVO.setCustomerCode(customerCode);
            baseCustomerBillingVO.setInvoiceTitle(customerName);
            baseCustomerBillingVO.setInvoiceTitleType("SystemDefaultHeader");
            baseCustomerBillingVO.setBillingAddress(defaultValue);
            baseCustomerBillingVO.setTaxpayerIdentificationNumber(defaultValue);
            baseCustomerBillingVO.setBillingTel(defaultValue);
            baseCustomerBillingVO.setBillingAccount(defaultValue);
            baseCustomerBillingVO.setBillingBank(defaultValue);
            baseCustomerBillingVO.setCreateTime(new Date());
            baseCustomerBillingVO.setUpdateTime(baseCustomerBillingVO.getCreateTime());
            BaseAssemblerUtil.insertFill(baseCustomerBillingVO, UserVoContextHolder.getUserVo());
            Response<Long> baseCustomerResponse = baseInfoClient.addSingleBilling(baseCustomerBillingVO);
            if (baseCustomerResponse.getCode() != ResponseCode.SUCCESS.getCode()) {
                throw new BusinessException(McnErrorCode.ADD_SYSTEM_CUSTOMER_BILLING_FAILED);
            }
            incomeContractAddDTO.setCustomerBillingId(baseCustomerResponse.getObj());
        } else {
            incomeContractAddDTO.setCustomerBillingId(originBilling.getBillingId());
        }

    }

    /**
     * 获取收入合同编号
     *
     * @return {@link List<String>}
     */
    @Override
    public List<String> getIncomeContractCode() {
        List<IncomeContract> dataList = incomeContractMapper.selectList(Wrappers.lambdaQuery(IncomeContract.class)
                .in(IncomeContract::getApprovalStatus, Arrays.asList(ApprovalStatusEnum.APPROVAL.code(), ApprovalStatusEnum.PASSED.code()))
                .eq(IncomeContract::getIsDelete, Boolean.FALSE)
                .orderByAsc(IncomeContract::getUpdateDate)
        );
        if (CollectionUtils.isEmpty(dataList)) {
            return null;
        }
        return dataList.stream().map(IncomeContract::getContractCode).distinct().collect(Collectors.toList());
    }

    @Override
    public IncomeContract getByCode(String contractCode, Long tenantId) {
        return incomeContractMapper.getByCode(contractCode, tenantId);
    }


    /**
     * 根据客户id获取收入合同编号
     *
     * @param customerId {@link Long}
     * @return {@link List<String>}
     */
    @Override
    public List<String> getIncomeCode(Long customerId) {
        List<IncomeContract> dataList = incomeContractMapper.selectList(Wrappers.lambdaQuery(IncomeContract.class)
                .select(IncomeContract::getContractCode).eq(IncomeContract::getCustomerId, customerId)
                .in(IncomeContract::getApprovalStatus, Arrays.asList(ApprovalStatusEnum.APPROVAL.code(), ApprovalStatusEnum.PASSED.code()))
                .eq(IncomeContract::getIsDelete, Boolean.FALSE));
        if (CollectionUtils.isEmpty(dataList)) {
            return null;
        }
        return dataList.stream().map(IncomeContract::getContractCode).distinct().collect(Collectors.toList());
    }

    @Override
    public Page<CusIncomeContractVO> getCusContractInfo(McnPage<CusIncomeContractVO> mcnPage, Long customerId) {
        /**
         * 查询客户关联收入合同
         */
        Page<CusIncomeContractVO> cusIncomeContractPage = incomeContractMapper.getCusIncomeContract(mcnPage, customerId, ApprovalEnum.getContractProcessIds());
        List<CusIncomeContractVO> contractList = cusIncomeContractPage.getRecords();
        if (CollectionUtil.isNotEmpty(contractList)) {
            List<Long> flowList = contractList.stream().map(CusIncomeContractVO::getFlowId).filter(Objects::nonNull).collect(Collectors.toList());
            // 审批名称

            JSONObject flowMapping = null;
            if (flowList.size() > 0) {
                flowMapping = approvalFlowService.getFlowStatus(flowList);
            }
            JSONObject finalFlowMapping = flowMapping;
            contractList.forEach(contract -> {
                if (Objects.nonNull(finalFlowMapping) && finalFlowMapping.size() > 0 && Objects.nonNull(contract.getFlowId())) {
                    contract.setFlowStatusName(finalFlowMapping.getString(contract.getFlowId().toString()));
                }
                contract.setApprovalStatusName(ApprovalStatusEnum.getStatusName(contract.getApprovalStatus()));
            });
        }
        return cusIncomeContractPage;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updatePayback(ChargeClearCallback dto, IncomeContract incomeContract, boolean isOfflineCommission) {
        BigDecimal diffAmount = null;
        if(StringUtils.isNotBlank(dto.getChargeSourceDetail())) {
            ContractExcutionOrder excutionOrder = contractExcutionOrderMapper.getByCode(dto.getChargeSourceDetail(), UserVoContextHolder.getTenantId());
            if(Objects.nonNull(excutionOrder)) {
                CalculationDevided calculationDevided = calculationDevidedMapper.selectOne(Wrappers.lambdaQuery(CalculationDevided.class)
                        .eq(CalculationDevided::getExcutionOrderId, excutionOrder.getId()));
                BigDecimal totalAmount = null;
                boolean needUpdatePaid = false;
                //差额处理
                if(IncomeContractTypeEnum.isFormalContract(incomeContract.getContractType()) && NumberCst.ZERO.equals(excutionOrder.getInSystemAdmin())) {
                    diffAmount = excutionOrder.getActualQuotedPrice().subtract(calculationDevided.getAmountReceivable());
                    totalAmount = calculationDevided.getAmountReceivable();
                    needUpdatePaid = true;
                } else if(IncomeContractTypeEnum.isLiveContract(incomeContract.getContractType()) &&
                        ObjectUtils.defaultIfNull(excutionOrder.getPlatformReport(), Boolean.FALSE).booleanValue()
                        && NumberCst.ZERO.equals(excutionOrder.getInSystemAdmin())) {
                    diffAmount = excutionOrder.getActualQuotedPrice().subtract(calculationDevided.getAmountReceivable());
                    totalAmount = calculationDevided.getAmountReceivable();
                    needUpdatePaid = true;
                } else {
                    totalAmount = excutionOrder.getActualQuotedPrice();
                }
                //只有执行创建时间>zxdPaybackStartDate的允许走执行单汇款逻辑
                if(excutionOrder.getCreateDate().after(DateUtil.parseDate(zxdPaybackEffectiveTimeStr))) {
                    //执行单-回款
                    contractExcutionOrderService.updatePayback(dto, excutionOrder, totalAmount, needUpdatePaid);
                }
            }
        }
        //收入合同-回款
        return this.amountCallback(isOfflineCommission ? MessageTopicEnum.OSC_CALLBACK_SR : MessageTopicEnum.PAYBACK_CALLBACK_SR,
                dto, incomeContract.getId(), diffAmount);
    }

    /**
     * @param topicEnum
     * @param callbackDTO
     * @return
     */
    private boolean amountCallback(MessageTopicEnum topicEnum, ChargeClearCallback callbackDTO, Long incomeContractId, BigDecimal diffAmount) {
        IncomeContract incomeContract = incomeContractMapper.selectById(incomeContractId);
        BusinessAssert.notNull(incomeContract, McnErrorCode.DATA_NOT_FOUND, String.format("【%s】查询不到该合同", topicEnum.getDesc()));
        String excuteCode = callbackDTO.getChargeSourceDetail();
        //是否冲销
        boolean isChargeAgainst = callbackDTO.getPaybackAmount().compareTo(BigDecimal.ZERO) == -1;
        //更新收入合同已开票金额
        IncomeContract updateIncomeContract = new IncomeContract();
        JSONObject jsonObject = new JSONObject();
        String messageHeader = null, messageBody = null;
        switch (topicEnum) {
            case OSC_CALLBACK_SR:
                if(!isChargeAgainst) {
                    BusinessAssert.isTrue(OfflineCommissionSettleStatusEnum.anyMatch(incomeContract.getOfflineCommissionSettleStatus(),
                            OfflineCommissionSettleStatusEnum.UN_PAYBACK, OfflineCommissionSettleStatusEnum.PART_PAYBACK),"线下佣金结算状态-非待回款或部分回款");
                }
                updateIncomeContract.setOfflineCommissionPaybackAmount(callbackDTO.getPaybackAmount().add(ObjectUtils.defaultIfNull(incomeContract.getOfflineCommissionPaybackAmount(), BigDecimal.ZERO)));
                BusinessAssert.isTrue(updateIncomeContract.getOfflineCommissionPaybackAmount().compareTo(BigDecimal.ZERO) != -1,
                        McnErrorCode.PARAM_ERROR, String.format("【%s】计算后回款金额为负数", topicEnum.getDesc()));
                BigDecimal offlineCommissionAmount = incomeContract.getOfflineCommissionAmount();

                if(BigDecimal.ZERO.compareTo(updateIncomeContract.getOfflineCommissionPaybackAmount()) == 0) {
                    updateIncomeContract.setOfflineCommissionSettleStatus(NumberCst.TWO);
                } else if (offlineCommissionAmount.compareTo(updateIncomeContract.getOfflineCommissionPaybackAmount()) == 1) {
                    updateIncomeContract.setOfflineCommissionSettleStatus(NumberCst.THREE);
                } else if (offlineCommissionAmount.compareTo(updateIncomeContract.getOfflineCommissionPaybackAmount()) == 0) {
                    updateIncomeContract.setOfflineCommissionSettleStatus(NumberCst.FOUR);
                } else {
                    //理论上不存在 回款金额大于线下佣金金额
                    updateIncomeContract.setOfflineCommissionSettleStatus(NumberCst.FOUR);
                }
                updateIncomeContract.setPayBackAmount(callbackDTO.getPaybackAmount().add(ObjectUtils.defaultIfNull(incomeContract.getPayBackAmount(), BigDecimal.ZERO)));
                this.fillPaybackStatus(topicEnum, incomeContract, updateIncomeContract);
                messageBody = JSONObject.toJSONString(callbackDTO);
                break;
            case PAYBACK_CALLBACK_SR:
                updateIncomeContract.setPayBackAmount(callbackDTO.getPaybackAmount().add(ObjectUtils.defaultIfNull(incomeContract.getPayBackAmount(), BigDecimal.ZERO)));
                if(StringUtils.isNotBlank(excuteCode) && Objects.nonNull(diffAmount)) {
                    messageHeader = "refund_diff_amount:"+excuteCode;
                }
                if(StringUtils.isNotBlank(messageHeader)) {
                    jsonObject.put("excuteCode", excuteCode);
                    jsonObject.put("diffAmount", diffAmount);
                    if(isChargeAgainst) {
                        String messageKey = StringUtils.joinWith("+", callbackDTO.getClearNo(), incomeContract.getContractCode());
                        MessageInfo messageInfo =  messageInfoService.getMessageByKey(topicEnum.name() , messageKey, messageHeader, incomeContract.getTenantId());
                        if(Objects.nonNull(messageInfo)) {
                            //如果费用拆分
                            updateIncomeContract.setPayBackAmount(updateIncomeContract.getPayBackAmount().subtract(diffAmount));
                            messageInfoService.deleteMessageByHeader(topicEnum.name() , messageHeader, incomeContract.getTenantId());
                        }
                        messageHeader = null;
                    } else {
                        if(messageInfoService.existMessageHeader(topicEnum.name() , messageHeader, incomeContract.getTenantId())) {
                            messageHeader = null;
                        } else {
                            jsonObject.put("refundDiffAmount", diffAmount);
                            updateIncomeContract.setPayBackAmount(updateIncomeContract.getPayBackAmount().add(diffAmount));
                        }
                    }
                }
                this.fillPaybackStatus(topicEnum, incomeContract, updateIncomeContract);
                jsonObject.put("totalAmount", updateIncomeContract.getPayBackAmount());
                jsonObject.put("billNo", callbackDTO.getClearNo());
                jsonObject.put("amount", callbackDTO.getPaybackAmount());
                jsonObject.put("contractCode", incomeContract.getContractCode());
                jsonObject.put("paybackDate", callbackDTO.getPaybackDate());
                messageBody = jsonObject.toJSONString();
                break;
            default:
                break;
        }
        updateIncomeContract.setPayBackDate(ObjectUtils.defaultIfNull(callbackDTO.getPaybackDate(), new Date()));
        String messageKey = StringUtils.joinWith(isChargeAgainst ? "-" : "+", callbackDTO.getClearNo(), incomeContract.getContractCode());
        String signature = CommonUtil.hmacMd5Hex(messageBody);
        MessageInfo messageInfo = MessageInfo.builder()
                .messageHeader(messageHeader)
                .messageTopic(topicEnum.name()).messageKey(messageKey)
                .messageBody(messageBody).signature(signature)
                .status(MessageStatusEnum.SUCCESS.getType())
                .tenantId(incomeContract.getTenantId())
                .build();
        if (!messageInfoService.addMessageInfo(messageInfo)) {
            MessageInfo entity = messageInfoService.selectOne(Wrappers.lambdaQuery(MessageInfo.class)
                    .eq(MessageInfo::getMessageTopic, topicEnum.name())
                    .eq(MessageInfo::getMessageKey, messageKey)
                    .eq(MessageInfo::getTenantId, incomeContract.getTenantId())
                    .eq(MessageInfo::getIsDelete, Boolean.FALSE));
            BusinessAssert.notNull(entity, McnErrorCode.BUSINESS_ERROR, String.format("【%s】数据幂等处理异常", topicEnum.getDesc()));
            //判断消息内容签名，如果相等，重复回调
            if (signature.equals(entity.getSignature())) {
                //也可以进一步比较金额
                return true;
            }
            switch (topicEnum) {
                case OSC_CALLBACK_SR:
                    ChargeClearCallback oscPayload = JSONObject.parseObject(entity.getMessageBody(), ChargeClearCallback.class);
                    throw new BusinessException(McnErrorCode.BUSINESS_ERROR.code(),
                            String.format("【%s】重复请求！上次回调：核销单号=%s，金额=%s，收入合同=%s", topicEnum.getDesc(), oscPayload.getClearNo(), oscPayload.getPaybackAmount(), oscPayload.getSourceBillCode()));
                case PAYBACK_CALLBACK_SR:
                    JSONObject payload = JSONObject.parseObject(entity.getMessageBody());
                    String preBillNo = payload.getString("billNo");
                    BigDecimal preAmount = payload.getBigDecimal("amount");
                    String preContractCode = payload.getString("contractCode");
                    throw new BusinessException(McnErrorCode.BUSINESS_ERROR.code(),
                            String.format("【%s】重复请求！上次回调：单据号=%s，金额=%s，合同号=%s", topicEnum.getDesc(), preBillNo, preAmount, preContractCode));
                default:
                    break;
            }
        }
        updateIncomeContract.setId(incomeContract.getId());
        updateIncomeContract.setUpdateBy(callbackDTO.getOperatorId());
        updateIncomeContract.setUpdateName(callbackDTO.getOperatorName());
        updateIncomeContract.setUpdateDate(new Date());
        boolean result = incomeContractMapper.updateById(updateIncomeContract) > 0;
        if (result) {
            //操作日志
            EventPublisher.post(OperateLogEvent.builder().businessId(incomeContract.getId())
                    .businessType(LogBusinessTypeEnum.INCOME_CONTRACT)
                    .remark(callbackDTO.getClearNo())
                    .compare(incomeContract, incomeContractMapper.selectById(incomeContract.getId()))
                    .build());
        }
        return result;
    }

    private void fillPaybackStatus(MessageTopicEnum topicEnum, IncomeContract incomeContract, IncomeContract updateIncomeContract) {
        BusinessAssert.isTrue(updateIncomeContract.getPayBackAmount().compareTo(BigDecimal.ZERO) != -1,
                McnErrorCode.PARAM_ERROR, String.format("【%s】计算后已回款金额为负数", topicEnum.getDesc()));
        if(CommonUtil.greaterThanZero(incomeContract.getBusinessAmount()) && BigDecimal.ZERO.compareTo(updateIncomeContract.getPayBackAmount()) == 0) {
            updateIncomeContract.setPayBackStatus(NumberCst.ZERO);
        } else if (incomeContract.getBusinessAmount().compareTo(updateIncomeContract.getPayBackAmount()) == 1) {
            updateIncomeContract.setPayBackStatus(NumberCst.ONE);
        } else if (incomeContract.getBusinessAmount().compareTo(updateIncomeContract.getPayBackAmount()) == 0) {
            switch (topicEnum) {
                case PAYBACK_CALLBACK_SR:
                    //如果是框架合同、佣金线下比例不为0且线下佣金状态非已回款，置为部分回款
                    if(IncomeContractTypeEnum.isLiveContract(incomeContract.getContractType()) && !"0".equals(incomeContract.getOfflineCommissionRate())
                            && !OfflineCommissionSettleStatusEnum.ALL_PAYBACK.getCode().equals(incomeContract.getOfflineCommissionSettleStatus())) {
                        updateIncomeContract.setPayBackStatus(NumberCst.ONE);
                    } else {
                        updateIncomeContract.setPayBackStatus(NumberCst.TWO);
                    }
                    break;
                default:
                    updateIncomeContract.setPayBackStatus(NumberCst.TWO);
                    break;
            }
        } else {
            //理论上不存在 回款金额大于合同金额
            updateIncomeContract.setPayBackStatus(NumberCst.TWO);
        }
    }

    /**
     * 获取客户档案金额
     *
     * @param customerId {@link Long}
     * @return {@link CustomerFileAmount}
     */
    @Override
    public CustomerFileAmount getCustomerFileAmount(Long customerId) {
        BigDecimal historyTotalAmount = incomeContractMapper.getHistoryAmount(customerId);
        BigDecimal collectionAmount = incomeContractMapper.getCollectionAmount(customerId);
        CustomerFileAmount customerFileAmount = new CustomerFileAmount();
        customerFileAmount.setHistoryTotalAmount(historyTotalAmount);
        customerFileAmount.setCollectionAmount(collectionAmount);
        return customerFileAmount;
    }

    @Override
    public List<Long> getRelatedIncomeContract(Long billingId) {
        List<IncomeContract> incomeContracts = incomeContractMapper.selectList(Wrappers.lambdaQuery(IncomeContract.class)
                .eq(IncomeContract::getCustomerBillingId, billingId)
                .eq(IncomeContract::getIsDelete, Boolean.FALSE)
                .ne(IncomeContract::getApprovalStatus, ApprovalStatusEnum.INVALID.code()));
        return incomeContracts.stream().map(IncomeContract::getId).collect(Collectors.toList());
    }

    /**
     * 根据客户名称获取收入合同编号
     *
     * @param customerId {@link Long}
     * @return {@link List}
     */
    @Override
    public List<IncomeContract> getIncomeCodesByCustomerId(Long customerId) {
        return incomeContractMapper.selectList(Wrappers.lambdaQuery(IncomeContract.class).eq(IncomeContract::getCustomerId, customerId).eq(IncomeContract::getApprovalStatus, ApprovalStatusEnum.PASSED.getCode()).orderByDesc(IncomeContract::getUpdateDate));
    }

    /**
     * 获取收入合同金额
     *
     * @param incomeCode {@link String}
     * @return {@link BigDecimal}
     */
    @Override
    public BigDecimal getIncomeContractAmount(String incomeCode) {
        IncomeContract incomeContract = incomeContractMapper.selectOne(Wrappers.lambdaQuery(IncomeContract.class).eq(IncomeContract::getContractCode, incomeCode));
        return incomeContract.getBusinessAmount();
    }

    @Override
    public IncomeAmountSumVO getSumAmount(IncomeContractSearchDTO dto) {
        dto.setAlias("ic.");
        dto.setProcessIds(ApprovalEnum.getContractProcessIds());
        if (CollectionUtils.isNotEmpty(dto.getFlowStatus())) {
            List<Long> allList = approvalFlowService.getSrcList(dto.getFlowStatus(), dto.getProcessIds());
            if (CollectionUtil.isEmpty(allList)) {
                return new IncomeAmountSumVO();
            }
            dto.setSrcIds(allList);
        }
        IncomeAmountSumVO sumAmount = incomeContractMapper.getSumAmount(dto);
        sumAmount.setSumUnPayBackAmount(sumAmount.getSumBusinessAmount().subtract(sumAmount.getSumPayBackAmount()));
        return sumAmount;
    }

    @Override
    public ApprovalOperationVO changeApproval(ChangeApprovalDTO dto, Long billId) {
        IncomeContract entity = incomeContractMapper.selectById(billId);
        BusinessAssert.notNull(entity, McnErrorCode.INCOME_NOT_EXISTS);
        BusinessAssert.isFalse(ApprovalStatusEnum.isInvalid(entity.getApprovalStatus()), McnErrorCode.DATA_OPERATION_NOT_SUPPORTED, "合同已作废，不允许操作！");
        BusinessAssert.isTrue(ApprovalStatusEnum.isApproval(entity.getApprovalStatus()), McnErrorCode.DATA_OPERATION_NOT_SUPPORTED, "合同非审批中，不允许操作！");
        ApprovalOperationVO approvalOperationVO;
        if(!dto.getApprovalFlag().booleanValue()) {
            approvalOperationVO = approvalFlowService.approvalChange(dto.getApprovalId(), JSON.toJSONString(dto.getParamMap()), Boolean.FALSE, dto.getRemark());
        } else {
            //兼容老的流程，暂不删除
            dto.getParamMap().put("containsOfflineCommission", CooperationTypeEnum.contains(entity.getCooperationType(), CooperationTypeEnum.OFFLINE_STRAIGHT_COMMISSION));
            String approvalParam = JSON.toJSONString(dto.getParamMap());
            if(CommonUtil.containsKeys(dto.getParamMap(), "offlineCommissionAmount")) {
                LiveContractFinanceSettlementDTO financeSettlementDTO =  JSON.parseObject(approvalParam, LiveContractFinanceSettlementDTO.class);
                financeSettlementDTO.setApprovalId(dto.getApprovalId());
                financeSettlementDTO.setId(entity.getId());
                ValidatorUtil.validate(financeSettlementDTO);
                IncomeContract updateIncomeContract = new IncomeContract();
                updateIncomeContract.setId(financeSettlementDTO.getId());
                updateIncomeContract.setOfflineCommissionAmount(financeSettlementDTO.getOfflineCommissionAmount());
                incomeContractMapper.updateById(updateIncomeContract);
                approvalOperationVO = approvalFlowService.approvalChange(dto.getApprovalId(), approvalParam, Boolean.TRUE, dto.getRemark());
                if(approvalOperationVO.isSuccess()) {
                    //操作日志
                    EventPublisher.post(OperateLogEvent.builder().businessId(entity.getId())
                            .businessType(LogBusinessTypeEnum.INCOME_CONTRACT)
                            .compare(entity, incomeContractMapper.selectById(billId)).build());
                }
            } else if(CommonUtil.containsKeys(dto.getParamMap(), "contractTag")) {
                IncomeContractLegalApprovalDTO legalApprovalDTO = JSON.parseObject(approvalParam, IncomeContractLegalApprovalDTO.class);
                legalApprovalDTO.setId(entity.getId());
                incomeContractMapper.updateByNoStrategy(Wrappers.lambdaUpdate(IncomeContract.class)
                        .set(IncomeContract::getContractTag, legalApprovalDTO.getContractTag())
                        .set(Objects.nonNull(legalApprovalDTO.getInSystemAdmin()), IncomeContract::getInSystemAdmin, legalApprovalDTO.getInSystemAdmin())
                        .set(IncomeContract::getUpdateBy, UserVoContextHolder.getUserId())
                        .set(IncomeContract::getUpdateName, UserVoContextHolder.getUserName())
                        .set(IncomeContract::getUpdateDate, new Date())
                        .eq(IncomeContract::getId, legalApprovalDTO.getId()));

                approvalOperationVO = approvalFlowService.approvalChange(dto.getApprovalId(), approvalParam, Boolean.TRUE, dto.getRemark());
            } else {
                approvalOperationVO = approvalFlowService.approvalChange(dto.getApprovalId(), approvalParam, Boolean.TRUE, dto.getRemark());
            }
        }
        BusinessAssert.isTrue(approvalOperationVO.isSuccess(), McnErrorCode.FLOW_ERROR, approvalOperationVO.getMessage());
        return approvalOperationVO;
    }

    /**
     * 审批流程并返回下一条
     *
     * @param dto
     * @param billId 单据ID
     * @return
     */
    @Override
    public NextNotifyVo changeApprovalNext(ChangeApprovalDTO dto, Long billId) {
        IncomeContract entity = incomeContractMapper.selectById(billId);
        BusinessAssert.notNull(entity, McnErrorCode.INCOME_NOT_EXISTS);
        BusinessAssert.isFalse(ApprovalStatusEnum.isInvalid(entity.getApprovalStatus()), McnErrorCode.DATA_OPERATION_NOT_SUPPORTED, "合同已作废，不允许操作！");
        BusinessAssert.isTrue(ApprovalStatusEnum.isApproval(entity.getApprovalStatus()), McnErrorCode.DATA_OPERATION_NOT_SUPPORTED, "合同非审批中，不允许操作！");
        NextNotifyVo nextNotifyVo;
        if(!dto.getApprovalFlag().booleanValue()) {
            nextNotifyVo = approvalFlowService.approvalChangeNext(dto.getApprovalId(), JSON.toJSONString(dto.getParamMap()), Boolean.FALSE, dto.getRemark());
        } else {
            dto.getParamMap().put("containsOfflineCommission", CooperationTypeEnum.contains(entity.getCooperationType(), CooperationTypeEnum.OFFLINE_STRAIGHT_COMMISSION));
            String approvalParam = JSON.toJSONString(dto.getParamMap());
            if(CommonUtil.containsKeys(dto.getParamMap(), "offlineCommissionAmount")) {
                LiveContractFinanceSettlementDTO financeSettlementDTO =  JSON.parseObject(approvalParam, LiveContractFinanceSettlementDTO.class);
                financeSettlementDTO.setApprovalId(dto.getApprovalId());
                financeSettlementDTO.setId(entity.getId());
                ValidatorUtil.validate(financeSettlementDTO);
                IncomeContract updateIncomeContract = new IncomeContract();
                updateIncomeContract.setId(financeSettlementDTO.getId());
                updateIncomeContract.setOfflineCommissionAmount(financeSettlementDTO.getOfflineCommissionAmount());
                incomeContractMapper.updateById(updateIncomeContract);
                nextNotifyVo = approvalFlowService.approvalChangeNext(dto.getApprovalId(), approvalParam, Boolean.TRUE, dto.getRemark());
                EventPublisher.post(OperateLogEvent.builder().businessId(entity.getId())
                        .businessType(LogBusinessTypeEnum.INCOME_CONTRACT)
                        .compare(entity, incomeContractMapper.selectById(billId)).build());
            } else if(CommonUtil.containsKeys(dto.getParamMap(), "contractTag")) {
                IncomeContractLegalApprovalDTO legalApprovalDTO = JSON.parseObject(approvalParam, IncomeContractLegalApprovalDTO.class);
                legalApprovalDTO.setId(entity.getId());
                ValidatorUtil.validate(legalApprovalDTO);
                incomeContractMapper.updateByNoStrategy(Wrappers.lambdaUpdate(IncomeContract.class)
                        .set(IncomeContract::getContractTag, legalApprovalDTO.getContractTag())
                        .set(Objects.nonNull(legalApprovalDTO.getInSystemAdmin()), IncomeContract::getInSystemAdmin, legalApprovalDTO.getInSystemAdmin())
                        .set(IncomeContract::getUpdateBy, UserVoContextHolder.getUserId())
                        .set(IncomeContract::getUpdateName, UserVoContextHolder.getUserName())
                        .set(IncomeContract::getUpdateDate, new Date())
                        .eq(IncomeContract::getId, legalApprovalDTO.getId()));
                nextNotifyVo = approvalFlowService.approvalChangeNext(dto.getApprovalId(), JSON.toJSONString(dto.getParamMap()), Boolean.TRUE, dto.getRemark());
            } else {
                nextNotifyVo = approvalFlowService.approvalChangeNext(dto.getApprovalId(), approvalParam, Boolean.TRUE, dto.getRemark());
            }
        }
        return nextNotifyVo;
    }

    /**
     * 审批回调
     *
     * @param approvalFlowDTO 流程对对象
     * @param status          最后节点的同意 false 拒绝
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void approvalCallback(ApprovalFlowDTO approvalFlowDTO, Boolean status) {
        IncomeContract incomeContract = incomeContractMapper.selectById(approvalFlowDTO.getSrcId());
        BusinessAssert.notNull(incomeContract, McnErrorCode.INCOME_NOT_EXISTS);
        approvalFlowDTO.setSrcCode(incomeContract.getContractCode());
        approvalFlowDTO.addSubmitInfoIfNull(incomeContract);
        ApprovalEnum approvalEnum = ApprovalEnum.getEnumByContractType(incomeContract.getContractType());
        if (Objects.isNull(status)) {
            //审批流配置-接入待办
            return;
        }
        //流程审批结束
        Integer approvalStatus = status.booleanValue() ? ApprovalStatusEnum.PASSED.code() : ApprovalStatusEnum.REJECTED.code();
        if (ApprovalStatusEnum.anyMatch(incomeContract.getApprovalStatus(), ApprovalStatusEnum.PASSED, ApprovalStatusEnum.REJECTED)) {
            log.error("收入合同-流程审批结束重复回调，不做处理！approvalId={}", approvalFlowDTO.getApprovalId());
            return;
        }
        BigDecimal businessAmount = ObjectUtils.defaultIfNull(incomeContract.getBusinessAmount(), BigDecimal.ZERO);
        boolean eq1 = businessAmount.compareTo(BigDecimal.ZERO) == 0;
        BusinessAssert.isTrue(DistributedLockTemplate.execute(OperateLockEnum.INCOME_CONTRACT.generateKey(incomeContract.getId()), () -> {
            LambdaUpdateWrapper<IncomeContract> lambdaUpdateWrapper = Wrappers.lambdaUpdate(IncomeContract.class).eq(IncomeContract::getId, incomeContract.getId());
            //如果是直播合同
            if(IncomeContractTypeEnum.isLiveContract(incomeContract.getContractType())) {
                if(ApprovalStatusEnum.isRejected(approvalStatus)) {
                    lambdaUpdateWrapper.set(IncomeContract::getOfflineCommissionAmount, null);
                } else {
                    /*BigDecimal receivableTotalAmount = ObjectUtils.defaultIfNull(incomeContract.getPitFeeAmount(), BigDecimal.ZERO)
                            .add(ObjectUtils.defaultIfNull(incomeContract.getOfflineCommissionAmount(), BigDecimal.ZERO))
                            .add(ObjectUtils.defaultIfNull(incomeContract.getRoiServiceFee(), BigDecimal.ZERO))
                            .add(ObjectUtils.defaultIfNull(incomeContract.getAdAmount(), BigDecimal.ZERO));
                    lambdaUpdateWrapper.set(IncomeContract::getBusinessAmount, receivableTotalAmount);*/
                    if (eq1 && "0".equals(incomeContract.getOfflineCommissionRate())) {
                        lambdaUpdateWrapper.set(IncomeContract::getPayBackStatus, NumberCst.TWO)
                                .set(IncomeContract::getPayBackAmount, BigDecimal.ZERO)
                                .set(IncomeContract::getPayBackDate, new Date());
                    }
                }
            } else {
                if (eq1 && ApprovalStatusEnum.isPassed(approvalStatus)) {
                    lambdaUpdateWrapper.set(IncomeContract::getPayBackStatus, NumberCst.TWO)
                            .set(IncomeContract::getPayBackAmount, BigDecimal.ZERO)
                            .set(IncomeContract::getPayBackDate, new Date());
                }
            }
            return incomeContractMapper.updateByNoStrategy(lambdaUpdateWrapper
                    .set(IncomeContract::getApprovalStatus, approvalStatus)
                    .set(IncomeContract::getUpdateBy, UserVoContextHolder.getUserId())
                    .set(IncomeContract::getUpdateName, UserVoContextHolder.getUserName())
                    .set(IncomeContract::getUpdateDate, new Date()));
        }), McnErrorCode.FLOW_CALLBACK_HANDLE_EXCEPTION);

        IncomeContract newIncomeContract = incomeContractMapper.selectById(incomeContract.getId());
        //操作日志
        EventPublisher.post(OperateLogEvent.builder().businessId(incomeContract.getId())
                .businessType(LogBusinessTypeEnum.INCOME_CONTRACT)
                .compare(incomeContract,  newIncomeContract)
                .build(approvalFlowDTO.getUserId(), approvalFlowDTO.getUserName()));
        //更新执行单 - 是否下单至我司后台
        boolean eq2 = IncomeContractTypeEnum.isFormalContract(incomeContract.getContractType()) && Objects.nonNull(incomeContract.getInSystemAdmin());
        //审批通过
        if (ApprovalStatusEnum.isPassed(approvalStatus)) {
            if(eq1 || eq2) {
                List<ContractExcutionOrder> excutionOrders = CommonUtil.defaultList(contractExcutionOrderMapper.selectList(Wrappers.lambdaQuery(ContractExcutionOrder.class)
                        .eq(ContractExcutionOrder::getIncomeContractId, incomeContract.getId()).eq(ContractExcutionOrder::getIsDelete, NumberCst.ZERO)));
                excutionOrders.forEach(e -> {
                    ContractExcutionOrder updateItem = new ContractExcutionOrder();
                    updateItem.setId(e.getId());
                    if(eq1) {
                        updateItem.setPaybackAmount(BigDecimal.ZERO);
                        updateItem.setPaybackStatus(NumberCst.TWO);
                        updateItem.setPaybackDate(new Date());
                    }
                    if(eq2) {
                        updateItem.setInSystemAdmin(incomeContract.getInSystemAdmin());
                    }
                    contractExcutionOrderMapper.updateById(updateItem);
                    //操作日志
                    EventPublisher.post(OperateLogEvent.builder().businessId(e.getId())
                            .businessType(LogBusinessTypeEnum.EXECUTION_ORDER)
                            .compare(e,  contractExcutionOrderMapper.selectById(e.getId()))
                            .build(approvalFlowDTO.getUserId(), approvalFlowDTO.getUserName()));
                });
            }

            //如果非框架合同且合同金额等于0 则不产生费用
            if (IncomeContractTypeEnum.isLiveContract(incomeContract.getContractType()) || !eq1) {
                //生成费用推送财务系统
                incomeContractMessageProducer.sendRecordToMq(new ImmutablePair<>(incomeContract.getId(), Boolean.FALSE));
            }
        }
        approvalFlowService.sendNotify(approvalFlowDTO, incomeContract.getId(), incomeContract.getContractCode()
                , approvalEnum, status, incomeContract.getCreateBy(), incomeContract.getCreateName());
    }

    /**
     * 填充账号是否入驻
     *
     * @param excutionOrders
     */
    private void fillInSystemAdmin(List<ContractExcutionOrder> excutionOrders) {
        if (CollectionUtils.isEmpty(excutionOrders)) {
            return;
        }
        excutionOrders.forEach(e -> {
            e.setInSystemAdmin(starPlatformInfoService.getIsSystemAdmin(e.getStarPlatformInfoId(), e.getCooperationContent()));
        });
    }

    private void verifyParams(IncomeContract incomeContract, List<String> platformOrderNumbers, List<ContractExcutionOrder> excutionOrders) {
        BusinessAssert.notNull(incomeContract.getContractType(), ParamErrorCst.CONTRACT_TYPE_NOT_EMPTY);
        BusinessAssert.notNull(incomeContract.getCustomerId(), ParamErrorCst.CUSTOMER_NOT_EMPTY);
        //直播收入合同没有刊例总报价
        if (!IncomeContractTypeEnum.isLiveContract(incomeContract.getContractType())) {
            BusinessAssert.notNull(incomeContract.getTotalAmount(), ParamErrorCst.TOTAL_AMOUNT_NOT_EMPTY);
            BusinessAssert.notNull(incomeContract.getBusinessAmount(), ParamErrorCst.BUSINESS_AMOUNT_NOT_EMPTY);
            BusinessAssert.notBlank(incomeContract.getCooperateSource(), ParamErrorCst.CONTRACT_SOURCE_NOT_EMPTY);
            if (Objects.equals(incomeContract.getPerformanceShare(), NumberCst.ONE)) {
                BusinessAssert.notNull(incomeContract.getPerformanceSharerId(), ParamErrorCst.PERFORMANCE_SHARER_NOT_EMPTY);
            }
            BusinessAssert.notNull(incomeContract.getPerformanceShare(), ParamErrorCst.PERFORMANCE_SHARE_NOT_EMPTY);
        }
        BusinessAssert.notNull(incomeContract.getContractingId(), ParamErrorCst.COMPANY_SUBJECT_NOT_EMPTY);
        BusinessAssert.notBlank(incomeContract.getCompanyContractSubject(), ParamErrorCst.COMPANY_SUBJECT_NOT_EMPTY);
        BusinessAssert.notNull(incomeContract.getSignDate(), ParamErrorCst.SIGN_DATE_NOT_EMPTY);
        BusinessAssert.notBlank(incomeContract.getCooperateBrand(), ParamErrorCst.COOPERATE_BRAND_NOT_EMPTY);
        BusinessAssert.notBlank(incomeContract.getCooperateProduct(), ParamErrorCst.COOPERATE_PRODUCT_NOT_EMPTY);
        BusinessAssert.notBlank(incomeContract.getCooperateContent(), ParamErrorCst.COOPERATE_CONTENT_NOT_EMPTY);
        IncomeContractTypeEnum contractTypeEnum = IncomeContractTypeEnum.getType(incomeContract.getContractType());
        //定制化校验
        switch (contractTypeEnum) {
            //todo
            case LIVE_CONTRACT:
                // BusinessAssert.notNull(incomeContract.getPmId(), ParamErrorCst.PM_NOT_EMPTY);
                // BusinessAssert.notNull(incomeContract.getEarnestMoney(), ParamErrorCst.EARNEST_MONEY_NOT_EMPTY);
//                BusinessAssert.notNull(incomeContract.getCooperationType(), ParamErrorCst.COOPERATION_TYPE_NOT_EMPTY);
                BusinessAssert.notNull(incomeContract.getStarPlatformInfoId(), ParamErrorCst.ANCHOR_NOT_EMPTY);
                BusinessAssert.notNull(incomeContract.getLiveDate(), ParamErrorCst.LIVE_DATE_NOT_EMPTY);
                BusinessAssert.notNull(incomeContract.getPerformanceShare(), ParamErrorCst.PERFORMANCE_SHARE_NOT_EMPTY);
                if (Objects.equals(incomeContract.getPerformanceShare(), NumberCst.ONE)) {
                    BusinessAssert.notNull(incomeContract.getPerformanceSharerId(), ParamErrorCst.PERFORMANCE_SHARER_NOT_EMPTY);
                }
                // Assert.notNull(incomeContract.getLiveAmount(), ParamErrorCst.LIVE_AMOUNT_NOT_EMPTY);
//                if (Objects.equals(incomeContract.getContainsAdvertising(), NumberCst.ONE)) {
//                    BusinessAssert.notNull(incomeContract.getAdAmount(), ParamErrorCst.AD_AMOUNT_NOT_EMPTY);
//                    if (Objects.equals(incomeContract.getPerformanceShare(), NumberCst.ONE)) {
//                        BusinessAssert.notNull(incomeContract.getPerformanceShare(), ParamErrorCst.PERFORMANCE_SHARE_NOT_EMPTY);
//                        BusinessAssert.notNull(incomeContract.getPerformanceSharerId(), ParamErrorCst.PERFORMANCE_SHARER_NOT_EMPTY);
//                    }
//                }
//                BusinessAssert.notNull(incomeContract.getLiveContractCategory(), ParamErrorCst.LIVE_CONTRACT_CATEGORY);
                BusinessAssert.isTrue(CommonUtil.isNotEmptyArray(incomeContract.getContractFile()), ParamErrorCst.CONTRACT_FILE_NOT_EMPTY);
                List<ContractExcutionOrder> executionOrderList = contractExcutionOrderMapper.selectList(Wrappers.lambdaQuery(ContractExcutionOrder.class)
                        .eq(ContractExcutionOrder::getIsDelete, Boolean.FALSE)
                        .eq(ContractExcutionOrder::getIncomeContractId, incomeContract.getId())
                        .ne(ContractExcutionOrder::getApprovalStatus, ExcutionApprovalStatusEnum.INVALID.getCode()));
                BigDecimal reduce = new BigDecimal(String.valueOf(BigDecimal.ZERO));
                if (CollectionUtils.isNotEmpty(executionOrderList)) {
                    reduce = executionOrderList.stream().map(ContractExcutionOrder::getActualQuotedPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
                }
                BigDecimal advertisingTotal=ObjectUtils.defaultIfNull(incomeContract.getRoiAdvAmt(), BigDecimal.ZERO).add(ObjectUtils.defaultIfNull(incomeContract.getNoroiAdvAmt(),BigDecimal.ZERO));
                log.info("参与保比收入和不参与保比收入:{}",incomeContract.getRoiAdvAmt()+"｜"+incomeContract.getNoroiAdvAmt());
                log.info("执行单总金额之和1:{},",reduce+"｜"+advertisingTotal);
                if (reduce.compareTo(advertisingTotal) != 0){
                    throw new BusinessException(McnErrorCode.AMOUNT_OF_THE_EXECUTIO_NMUST_BE_EQUAL);
                }
                List<ContractExcutionOrder> list = executionOrderList.stream().filter(e -> e.getActualQuotedPrice().compareTo(BigDecimal.ZERO) == 0).collect(Collectors.toList());
                if (Objects.equals(incomeContract.getRoiAdvAmtEquity(), NumberCst.ONE)) {
                    if (Objects.equals(incomeContract.getNoroiAdvAmtEquity(), NumberCst.ONE)&&incomeContract.getNoroiAdvAmt().compareTo(BigDecimal.ZERO)==0){
                        if (list.size()<2){
                            throw new BusinessException(McnErrorCode.MUST_BE_ONE_ORDER_WITH_THE_AMOUNT_ZERO);
                        }
                    }else {
                        if (list.size() < 1) {
                            throw new BusinessException(McnErrorCode.MUST_BE_ONE_ORDER_WITH_THE_AMOUNT_ZERO);
                        }
                    }
                }else{
                    if (Objects.equals(incomeContract.getNoroiAdvAmtEquity(), NumberCst.ONE)&& incomeContract.getNoroiAdvAmt().compareTo(BigDecimal.ZERO)==0){
                        if (list.size()<1){
                            throw new BusinessException(McnErrorCode.MUST_BE_ONE_ORDER_WITH_THE_AMOUNT_ZERO);
                        }
                    }
                }
                break;
//            case FRAME_CONTRACT:
//                BusinessAssert.notNull(incomeContract.getLiveAmount(), ParamErrorCst.LIVE_AMOUNT_NOT_EMPTY);
//                BusinessAssert.notNull(incomeContract.getAdAmount(), ParamErrorCst.AD_AMOUNT_NOT_EMPTY);
            case SINGLE_ORDERS_INCOME_CONSTRACT:
            case ANNNUAL_DISCOUNT_INCOME_CONSTRACT:
                BusinessAssert.notNull(incomeContract.getPlatformOrders(), ParamErrorCst.PLATFORM_ORDER_NOT_EMPTY);
                BusinessAssert.isTrue(CommonUtil.isNotEmptyArray(incomeContract.getContractFile()), ParamErrorCst.CONTRACT_FILE_NOT_EMPTY);
                BusinessAssert.notNull(incomeContract.getInvoiceForm(), ParamErrorCst.INVOICE_FORM_NOT_EMPTY);
                break;
            case ANNUAL_DISCOUNT_FORMAL_CONSTRACT:
            case SINGLE_ORDERS_FORMAL_CONSTRACT:
                List<ContractExcutionOrder> platformReportIsFalseList = excutionOrders.stream().filter(x -> !Integer.valueOf(9).equals(x.getApprovalStatus()) && Boolean.FALSE.equals(x.getPlatformReport())).collect(Collectors.toList());
                BusinessAssert.isTrue(CollectionUtils.isEmpty(platformReportIsFalseList), ParamErrorCst.FORM_CONTRACT_PLATFORM_REPORT_IS_TRUE);
                Assert.isTrue(CommonUtil.isNotEmptyArray(incomeContract.getOrderScreenshot()), ParamErrorCst.ORDER_SCREENSHOT_NOT_EMPTY);
                break;
            default:
                break;
        }
        if (!IncomeContractTypeEnum.isLiveContract(incomeContract.getContractType())) {
            verifyInvoice(incomeContract);
            verifyAmountParam(incomeContract);
            checkPlatformOrderNumber(incomeContract, platformOrderNumbers);
        }
        //校验折扣审批单
        if (Objects.nonNull(incomeContract.getDiscountId())) {
            DiscountApproval discountApproval = discountApprovalService.getById(incomeContract.getDiscountId());
            BusinessAssert.notNull(discountApproval, McnErrorCode.DISCOUNT_NOT_EXISTS);
            BusinessAssert.isFalse(ApprovalStatusEnum.isInvalid(discountApproval.getApprovalStatus()), "关联的折扣返点审批单已作废！");
            //如果是单笔优惠，只允许关联1个
            if(discountApproval.getApprovalType().intValue() == DiscountApprovalEnum.SINGLE_DISCOUNT.code()) {
                BusinessAssert.isTrue(incomeContractMapper.notExist(Wrappers.lambdaQuery(IncomeContract.class)
                    .eq(IncomeContract::getIsDelete, NumberCst.ZERO).eq(IncomeContract::getDiscountId, discountApproval.getId())
                    .ne(IncomeContract::getId, incomeContract.getId()).ne(IncomeContract::getApprovalStatus, ApprovalStatusEnum.INVALID.getCode())
                ), "单笔优惠的折扣返点审批单不允许关联多个合同！");
            }
        }
    }


    /**
     * 直播合同校验金额(直播金额+广告金额=商务确认合同金额)
     *
     * @param incomeContract {@link IncomeContract}
     */
    private void verifyLiveContract(IncomeContract incomeContract) {
        if (IncomeContractTypeEnum.isLiveContract(incomeContract.getContractType())) {
            BigDecimal sum = incomeContract.getLiveAmount().add(incomeContract.getAdAmount());
            if (sum.compareTo(incomeContract.getBusinessAmount()) != 0) {
                throw new BusinessException(McnErrorCode.AMOUNT_IS_NOT_EQUAL);
            }
        }
    }

    /**
     * 校验刊例总报价及商务确认金额（合同金额）
     *
     * @param incomeContract {@link IncomeContract}
     */
    private void verifyAmountParam(IncomeContract incomeContract) {
        BigDecimal totalAmount = incomeContract.getTotalAmount();
        BigDecimal businessAmount = incomeContract.getBusinessAmount();
        //BigDecimal liveAmount = incomeContract.getLiveAmount();
        //BigDecimal adAmount = incomeContract.getAdAmount();
        //直播合同 允许合同金额为0
        if (IncomeContractTypeEnum.isLiveContract(incomeContract.getContractType())) {
            BusinessAssert.isTrue(businessAmount.compareTo(BigDecimal.ZERO) >= 0 && businessAmount.scale() <= 2, McnErrorCode.VERIFY_AMOUNT_ERROR, "请正确输入-商务确认金额（>=0 且 小数位<=2）");
            //BusinessAssert.isTrue(liveAmount.compareTo(BigDecimal.ZERO) >= 0 && liveAmount.scale() <= 2, McnErrorCode.VERIFY_AMOUNT_ERROR, "请正确输入-直播金额（>=0 且 小数位<=2）");
            //BusinessAssert.isTrue(adAmount.compareTo(BigDecimal.ZERO) >= 0 && adAmount.scale() <= 2, McnErrorCode.VERIFY_AMOUNT_ERROR, "请正确输入-广告金额（>=0 且 小数位<=2）");
            //BusinessAssert.isTrue(totalAmount.compareTo(BigDecimal.ZERO) >= 0 && totalAmount.scale() <= 2, McnErrorCode.VERIFY_AMOUNT_ERROR, "请正确输入-刊例总报价（>=0 且 小数位<=2）");
        } else {
            //BusinessAssert.isTrue(businessAmount.compareTo(BigDecimal.ZERO) > 0 && businessAmount.scale() <= 2, McnErrorCode.VERIFY_AMOUNT_ERROR, "请正确输入-商务确认金额（>0 且 小数位<=2）");
            //BusinessAssert.isTrue(totalAmount.compareTo(BigDecimal.ZERO) > 0 && totalAmount.scale() <= 2, McnErrorCode.VERIFY_AMOUNT_ERROR, "请正确输入-刊例总报价（>0 且 小数位<=2）");
        }
    }

    /**
     * 校验发票
     *
     * @param incomeContract
     */
    private static void verifyInvoice(IncomeContract incomeContract) {
        if (InvoiceFormEnum.NO_NEED_INVOICE.getType().equals(incomeContract.getInvoiceForm())) {
            return;
        }
        if (incomeContract.getCustomerBillingId() == null || StrUtil.isBlank(incomeContract.getCustomerSignSubject())) {
            throw new BusinessException(McnErrorCode.NO_CUSTOMER_SIGN_SUBJECT);
        }
        //需要开票
        if (InvoiceFormEnum.NEED_INVOICE.getType().equals(incomeContract.getInvoiceForm())) {
            if (incomeContract.getInvoiceType() == null) {
                throw new BusinessException(McnErrorCode.NO_INVOICE_TYPE);
            }
            if (StrUtil.isBlank(incomeContract.getInvoiceContent())) {
                throw new BusinessException(McnErrorCode.NO_INVOICE_CONTENT);
            }
        }
    }


    /**
     * 校验合同-平台订单号(兼容老数据)
     *
     * @param incomeContract
     * @param platformOrderNumbers
     */
    private void checkPlatformOrderNumber(IncomeContract incomeContract, List<String> platformOrderNumbers) {
        if (StringUtils.isAnyBlank(incomeContract.getFormalContractType(), incomeContract.getPlatformOrderNumber())) {
            return;
        }
        String[] split = incomeContract.getPlatformOrderNumber().split("//");
        List<String> list = Arrays.asList(split);
        List<String> collect = list.stream().distinct().collect(Collectors.toList());
        if (collect.size() != list.size()) {
            throw new BusinessException(McnErrorCode.PLATFORM_ORDER_NUMBER_REPEAT);
        }
        checkWhetherThePlatformOrderNumberExists(list, incomeContract, platformOrderNumbers);
    }

    /**
     * 校验平台订单号是否存在
     *
     * @param list {@link List<String>}
     */
    private void checkWhetherThePlatformOrderNumberExists(List<String> list, IncomeContract incomeContract, List<String> platformOrderNumbers) {
        List<String> numbers = new ArrayList<>();
        platformOrderNumbers.forEach(x -> {
            String[] split1 = x.split("//");
            List<String> asList = Arrays.asList(split1);
            numbers.addAll(asList);
        });
        String orderNumber = "";
        if (Objects.nonNull(incomeContract.getId())) {
            orderNumber = incomeContract.getPlatformOrderNumber();
        }
        String[] split = new String[0];
        if (Objects.nonNull(orderNumber)) {
            split = orderNumber.split("//");
        }
        List<String> stringList = Arrays.asList(split);
        List<String> collect = list.stream().filter(item -> !stringList.contains(item)).collect(Collectors.toList());
        String finalOrderNumber = orderNumber;
        collect.forEach(y -> {
            if (numbers.contains(y) && !incomeContract.getPlatformOrderNumber().equals(finalOrderNumber)) {
                throw new BusinessException(McnErrorCode.PLATFORM_ORDER_NUMBER_EXIST);
            }
        });
    }

    /**
     * 根据合同类型条件校验执行单金额 并返回是否需要更新收入合同预估成本
     *
     * @param contractType
     * @param contractExecutionOrders
     * @param businessAmount
     */
    private boolean verifyExcutionAmountIfNecessary(Integer contractType, List<ContractExcutionOrder> contractExecutionOrders, BigDecimal businessAmount) {
        if (IncomeContractTypeEnum.isLiveContract(contractType)) {
             //前面已做相关校验
        } else if (IncomeContractTypeEnum.isFrameContract(contractType)) {
            if (CollectionUtils.isNotEmpty(contractExecutionOrders)) {
                BigDecimal reduce = contractExecutionOrders.stream().filter(o -> !ExcutionApprovalStatusEnum.INVALID.getCode().equals(o.getApprovalStatus())).map(ContractExcutionOrder::getActualQuotedPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
                BusinessAssert.isTrue(reduce.compareTo(businessAmount) != 0, McnErrorCode.EXECUTION_ORDER_CANNOT_BE_DETERMINED);
            }
        } else {
            BusinessAssert.notEmpty(contractExecutionOrders, McnErrorCode.NO_EXECUTION);
            BigDecimal reduce = contractExecutionOrders.stream().filter(o -> !ExcutionApprovalStatusEnum.INVALID.getCode().equals(o.getApprovalStatus())).map(ContractExcutionOrder::getActualQuotedPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
            BusinessAssert.isTrue(reduce.compareTo(businessAmount) == 0, McnErrorCode.EXCEEDING_CONTRACT_AMOUNT);
        }
        return true;
    }

    /**
     * 提醒重复数据录入
     *
     * @param approvalStatus
     * @param oldExcutionOrders
     */
    @Override
    public void remindDuplicateEntry(Integer approvalStatus, List<ContractExcutionOrder> oldExcutionOrders) {
        if (!ApprovalStatusEnum.isApproval(approvalStatus)) {
            return;
        }
        List<ContractExcutionOrder> excutionOrders = CommonUtil.defaultList(oldExcutionOrders).stream().filter(e -> !ExcutionApprovalStatusEnum.isInvalid(e.getApprovalStatus())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(excutionOrders)) {
            /**
             * 比较发布日期区间
             */
            for (ContractExcutionOrder excutionOrder : excutionOrders) {
                if (ExcutionApprovalStatusEnum.isInvalid(excutionOrder.getApprovalStatus())) {
                    continue;
                }
                List<ContractExcutionOrder> repeatedContractExcutionOrders = excutionOrders.stream().filter(e ->
                                !excutionOrder.equals(e) && StringUtils.equals(excutionOrder.getBrandName(), e.getBrandName())
                                && excutionOrder.getStarPlatformInfoId().equals(e.getStarPlatformInfoId())
                                && ObjectUtils.defaultIfNull(excutionOrder.getRealAmount(), BigDecimal.ZERO).compareTo(ObjectUtils.defaultIfNull(e.getRealAmount(), BigDecimal.ZERO)) == 0
                                 && (DateUtil.contains(excutionOrder.getPromisePublishDate(), e.getPromisePublishDate(), e.getPromisePublishDateEnd())
                                        || DateUtil.contains(excutionOrder.getPromisePublishDateEnd(), e.getPromisePublishDate(), e.getPromisePublishDateEnd()))
                        ).collect(Collectors.toList());
                BusinessAssert.isTrue(CollectionUtils.isEmpty(repeatedContractExcutionOrders), "合同内存在执行单重复！请仔细检查「品牌」+「发布平台」+「发布日期」+「红人平台昵称」+「内容实际报价」");
            }
            List<RepeatedExcutionOrderData> repeatedDataList = new ArrayList<>(8);
            /**
             * 比较实际发布日期
             */
            if(CollectionUtils.isEmpty(repeatedDataList)) {
                List<Long> excludedIds = excutionOrders.stream().map(ContractExcutionOrder::getId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
                for (ContractExcutionOrder excutionOrder : excutionOrders) {
                    if (ExcutionApprovalStatusEnum.isInvalid(excutionOrder.getApprovalStatus())) {
                        continue;
                    }
                    List<ContractExcutionOrder> repeatedContractExcutionOrders = contractExcutionOrderMapper.getRepeatedContractExcutionOrders(excludedIds,
                            excutionOrder.getStarPlatformInfoId(), excutionOrder.getBrandName(),
                            excutionOrder.getRealAmount(), excutionOrder.getPromisePublishDate(), excutionOrder.getPromisePublishDateEnd());
                    if (CollectionUtils.isNotEmpty(repeatedContractExcutionOrders)) {
                        List<KVPair<Long, String>> repeatedList = repeatedContractExcutionOrders.stream().map(e -> new KVPair<>(e.getId(), e.getExcuteCode())).collect(Collectors.toList());
                        repeatedDataList.add(new RepeatedExcutionOrderData(Objects.nonNull(excutionOrder.getId()) ? excutionOrder.getExcuteCode() : excutionOrder.getIntentionCode(), repeatedList));
                    }
                }
            }
            if(CollectionUtils.isNotEmpty(repeatedDataList)) {
                throw new RepeatedDataExeception(McnErrorCode.EXCUTION_ORDER_ADD_REPEATED, repeatedDataList);
            }
        }
    }

    @Override
    public Boolean distributeLiveCommission(Long id) {
        IncomeContract incomeContract = incomeContractMapper.selectOne(Wrappers.lambdaQuery(IncomeContract.class)
                .eq(IncomeContract::getId, id).eq(IncomeContract::getIsDelete, NumberCst.ZERO));
        BusinessAssert.notNull(incomeContract, McnErrorCode.INCOME_NOT_EXISTS);
        //合同类型为框架合同、合同审批通过、合同回款状态已回款、直播提成结算状态未结算
        BusinessAssert.isTrue(IncomeContractTypeEnum.isLiveContract(incomeContract.getContractType()), "非框架合同，不允许操作");
        BusinessAssert.isTrue(ApprovalStatusEnum.isPassed(incomeContract.getApprovalStatus()),  "非审批通过，不允许操作");
        BusinessAssert.isTrue(PaybackStatusEnum.anyMatch(incomeContract.getPayBackStatus(), PaybackStatusEnum.PART, PaybackStatusEnum.ALL),  "尚未回款，不允许操作");
        BusinessAssert.isTrue(CommonSettleStatusEnum.isUnsettled(incomeContract.getLiveCommissionSettleStatus()),  "非未结算，不允许操作");
        IncomeContract updateIncomeContract = new IncomeContract();
        updateIncomeContract.setId(incomeContract.getId());
        updateIncomeContract.setLiveCommissionSettleStatus(CommonSettleStatusEnum.SETTLED.getCode());
        incomeContractMapper.updateById(updateIncomeContract);
        //操作日志
        EventPublisher.post(OperateLogEvent.builder().businessId(incomeContract.getId())
                .businessType(LogBusinessTypeEnum.INCOME_CONTRACT)
                .compare(incomeContract, incomeContractMapper.selectById(incomeContract.getId()))
                .build());
        return Boolean.TRUE;
    }
}
